Results 1 to 10 of 10

Thread: Extract thumbnail image from a file without reading the whole file

  1. #1

    Thread Starter
    l33t! MrPolite's Avatar
    Join Date
    Sep 2001
    Posts
    4,428

    Extract thumbnail image from a file without reading the whole file

    this is the VB.NET version of the article I posted here in the C# CodeBank. I wrote the VB code by decompiling the C# code I already had, so no comments for the code. And some parts may be slightly weird but it works


    You could use Image.GetThumbnailImage() to get a thumbnail of an already loaded image, but if you have a lot of images and you do that, it'd be fairly slow because you would have to load all the images.
    Alternatively most images taken with cameras have a thumbnail of the image stored in the image metadata, and that can be accessed without loading the image as a whole.
    If you have .NET 1.1 installed then you can do this:
    VB Code:
    1. ' Please do not remove :)
    2. ' Written by Kourosh Derakshan
    3. '
    4.  
    5. Imports System.IO
    6. Imports System.Drawing.Imaging
    7.  
    8. Private Const THUMBNAIL_DATA As Integer = 20507
    9.  
    10.     Private Function GetThumbnail(ByVal path As String) As Image
    11.         Dim stream1 As FileStream = File.OpenRead(path)
    12.         Dim image1 As Image = Image.FromStream(stream1, False, False)
    13.         Dim flag1 As Boolean = False
    14.         Dim num1 As Integer
    15.         For num1 = 0 To image1.PropertyIdList.Length - 1
    16.             If (image1.PropertyIdList(num1) = Me.THUMBNAIL_DATA) Then
    17.                 flag1 = True
    18.                 Exit For
    19.             End If
    20.         Next num1
    21.         If Not flag1 Then
    22.             Return Nothing
    23.         End If
    24.         Dim item1 As PropertyItem = image1.GetPropertyItem(Me.THUMBNAIL_DATA)
    25.         stream1.Close()
    26.         image1.Dispose()
    27.         Dim buffer1 As Byte() = item1.Value
    28.         Dim stream2 As New MemoryStream(buffer1.Length)
    29.         stream2.Write(buffer1, 0, buffer1.Length)
    30.         Return Image.FromStream(stream2)
    31.     End Function


    If you want support for .NET 1.0 also, you can try this code below
    VB Code:
    1. ' Please do not remove :)
    2. ' Written by Kourosh Derakshan
    3. '
    4.  
    5. Imports System
    6. Imports System.IO
    7. Imports System.Drawing
    8. Imports System.Drawing.Imaging
    9. Imports System.Runtime.InteropServices
    10.  
    11. Public MustInherit Class ExifThumbReader
    12.     <DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)> _
    13.     Private Shared Function GdipDisposeImage(ByVal image As IntPtr) As Integer
    14.     End Function
    15.  
    16.     <DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)> _
    17.     Friend Shared Function GdipGetPropertyItem(ByVal image As IntPtr, ByVal propid As Integer, ByVal size As Integer, ByVal buffer As IntPtr) As Integer
    18.     End Function
    19.  
    20.     <DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)> _
    21.     Friend Shared Function GdipGetPropertyItemSize(ByVal image As IntPtr, ByVal propid As Integer, <Out()> ByRef size As Integer) As Integer
    22.     End Function
    23.  
    24.     <DllImport("gdiplus.dll", CharSet:=CharSet.Unicode, ExactSpelling:=True)> _
    25.     Friend Shared Function GdipLoadImageFromFile(ByVal filename As String, <Out()> ByRef image As IntPtr) As Integer
    26.     End Function
    27.  
    28.     Private Const THUMBNAIL_DATA As Integer = 20507
    29.  
    30.  
    31.     Public Shared Function ReadThumb(ByVal imagePath As String) As Image
    32.         Dim image1 As Image
    33.         Dim ptr1 As IntPtr = IntPtr.Zero
    34.         Dim buffer As IntPtr = IntPtr.Zero
    35.         Dim ret As Integer = ExifThumbReader.GdipLoadImageFromFile(imagePath, ptr1)
    36.         Try
    37.             Dim thumbSize As Integer
    38.             If (ret <> 0) Then
    39.                 Throw ExifThumbReader.createException(ret)
    40.             End If
    41.             ret = ExifThumbReader.GdipGetPropertyItemSize(ptr1, ExifThumbReader.THUMBNAIL_DATA, thumbSize)
    42.             If (ret = 19) Then
    43.                 Return Nothing
    44.             End If
    45.             If (ret <> 0) Then
    46.                 Throw ExifThumbReader.createException(ret)
    47.             End If
    48.             buffer = Marshal.AllocHGlobal(thumbSize)
    49.             If (buffer.Equals(IntPtr.Zero)) Then
    50.                 Throw ExifThumbReader.createException(3)
    51.             End If
    52.             ret = ExifThumbReader.GdipGetPropertyItem(ptr1, ExifThumbReader.THUMBNAIL_DATA, thumbSize, buffer)
    53.             If (ret <> 0) Then
    54.                 Throw ExifThumbReader.createException(ret)
    55.             End If
    56.             image1 = ExifThumbReader.convertFromMemory(buffer)
    57.         Finally
    58.             If (Not buffer.Equals(IntPtr.Zero)) Then
    59.                 Marshal.FreeHGlobal(buffer)
    60.             End If
    61.             ExifThumbReader.GdipDisposeImage(ptr1)
    62.         End Try
    63.         Return image1
    64.     End Function
    65.  
    66.     Private Shared Function createException(ByVal gdipErrorCode As Integer) As Exception
    67.         Select Case gdipErrorCode
    68.             Case 1
    69.                 Return New ExternalException("Gdiplus Generic Error", -2147467259)
    70.             Case 2
    71.                 Return New ArgumentException("Gdiplus Invalid Parameter")
    72.             Case 3
    73.                 Return New OutOfMemoryException("Gdiplus Out Of Memory")
    74.             Case 4
    75.                 Return New InvalidOperationException("Gdiplus Object Busy")
    76.             Case 5
    77.                 Return New OutOfMemoryException("Gdiplus Insufficient Buffer")
    78.             Case 7
    79.                 Return New ExternalException("Gdiplus Generic Error", -2147467259)
    80.             Case 8
    81.                 Return New InvalidOperationException("Gdiplus Wrong State")
    82.             Case 9
    83.                 Return New ExternalException("Gdiplus Aborted", -2147467260)
    84.             Case 10
    85.                 Return New FileNotFoundException("Gdiplus File Not Found")
    86.             Case 11
    87.                 Return New OverflowException("Gdiplus Over flow")
    88.             Case 12
    89.                 Return New ExternalException("Gdiplus Access Denied", -2147024891)
    90.             Case 13
    91.                 Return New ArgumentException("Gdiplus Unknown Image Format")
    92.             Case 18
    93.                 Return New ExternalException("Gdiplus Not Initialized", -2147467259)
    94.             Case 20
    95.                 Return New ArgumentException("Gdiplus Property Not Supported Error")
    96.         End Select
    97.         Return New ExternalException("Gdiplus Unknown Error", -2147418113)
    98.     End Function
    99.  
    100.  
    101.  
    102.  
    103.     Private Shared Function convertFromMemory(ByVal thumbData As IntPtr) As Image
    104.         Dim prop As propertyItemInternal = CType(Marshal.PtrToStructure(thumbData, GetType(propertyItemInternal)), propertyItemInternal)
    105.         Dim buffer As Byte() = prop.Value
    106.         Dim stream As New MemoryStream(buffer.Length)
    107.         stream.Write(buffer, 0, buffer.Length)
    108.         Return Image.FromStream(stream)
    109.     End Function
    110.  
    111.  
    112.  
    113.  
    114.  
    115.  
    116.  
    117.     <StructLayout(LayoutKind.Sequential)> _
    118.     Private Class propertyItemInternal
    119.  
    120.         Public ReadOnly Property Value() As Byte()
    121.             Get
    122.                 Dim buffer1 As Byte() = New Byte(Me.len - 1) {}
    123.                 Marshal.Copy(Me.valuePtr, buffer1, 0, Me.len)
    124.                 Return buffer1
    125.             End Get
    126.         End Property
    127.  
    128.  
    129.  
    130.  
    131.         Public id As Integer
    132.         Public len As Integer
    133.         Public type As Short
    134.         Public valuePtr As IntPtr
    135.     End Class
    136. End Class




    I've tested both codes above and they worked for images with and without thumbnails. But I havent gone through the code line by line... I just some minor issues from decompiling if you want to read the comments see the C# post
    Last edited by MrPolite; Jun 5th, 2005 at 04:35 PM.
    rate my posts if they help ya!
    Extract thumbnail without reading the whole image file: (C# - VB)
    Apply texture to bitmaps: (C# - VB)
    Extended console library: (VB)
    Save JPEG with a certain quality (image compression): (C# - VB )
    VB.NET to C# conversion tips!!

  2. #2
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: Extract thumbnail image from a file without reading the whole file

    Optimised it a bit, hope you don't mind. Good work though mate.

    VB Code:
    1. Imports System.IO
    2. Imports System.Drawing.Imaging
    3.  
    4. Private Const THUMBNAIL_DATA As Integer = 20507
    5.  
    6.     Private Function GetThumbnail(ByVal path As String) As Image
    7.  
    8.         Try
    9.             '################
    10.             Dim strm As Stream = New FileStream(path.Trim, FileMode.Open, FileAccess.Read, FileShare.Read)
    11.             Dim img As Image = Image.FromStream(strm, False, False)
    12.  
    13.             If Array.IndexOf(img.PropertyIdList, THUMBNAIL_DATA) > -1 Then
    14.                 Dim item1 As PropertyItem = img.GetPropertyItem(THUMBNAIL_DATA)
    15.                 strm.Close()
    16.                 img.Dispose()
    17.                 Dim buffer1 As Byte() = item1.Value
    18.                 strm = New MemoryStream(buffer1.Length)
    19.                 strm.Write(buffer1, 0, buffer1.Length)
    20.                 Return img Image.FromStream(strm)
    21.             Else
    22.                 Return Nothing
    23.             End If
    24.             '################
    25.         Catch ex As Exception
    26.             Throw ex
    27.         End Try
    28.  
    29.     End Function
    Last edited by wossname; Jun 2nd, 2005 at 12:46 PM.
    I don't live here any more.

  3. #3

    Thread Starter
    l33t! MrPolite's Avatar
    Join Date
    Sep 2001
    Posts
    4,428

    Re: Extract thumbnail image from a file without reading the whole file

    you idiot you didnt optimize it, you ruined it!
    do NOT close the stream at the end! you'll get an out of memory exception if you actually load an image with a thumbnail
    and naah I dont mind you optimizing it since I didnt really write the vb.net code line by line
    rate my posts if they help ya!
    Extract thumbnail without reading the whole image file: (C# - VB)
    Apply texture to bitmaps: (C# - VB)
    Extended console library: (VB)
    Save JPEG with a certain quality (image compression): (C# - VB )
    VB.NET to C# conversion tips!!

  4. #4
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: Extract thumbnail image from a file without reading the whole file

    Worked OK for me
    I don't live here any more.

  5. #5

    Thread Starter
    l33t! MrPolite's Avatar
    Join Date
    Sep 2001
    Posts
    4,428

    Re: Extract thumbnail image from a file without reading the whole file

    you tested it on the wrong image!
    rate my posts if they help ya!
    Extract thumbnail without reading the whole image file: (C# - VB)
    Apply texture to bitmaps: (C# - VB)
    Extended console library: (VB)
    Save JPEG with a certain quality (image compression): (C# - VB )
    VB.NET to C# conversion tips!!

  6. #6

    Thread Starter
    l33t! MrPolite's Avatar
    Join Date
    Sep 2001
    Posts
    4,428

    Re: Extract thumbnail image from a file without reading the whole file

    http://msdn.microsoft.com/library/en...asp?frame=true

    "You must keep the stream open for the lifetime of the Image object"
    rate my posts if they help ya!
    Extract thumbnail without reading the whole image file: (C# - VB)
    Apply texture to bitmaps: (C# - VB)
    Extended console library: (VB)
    Save JPEG with a certain quality (image compression): (C# - VB )
    VB.NET to C# conversion tips!!

  7. #7
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,682

    Re: Extract thumbnail image from a file without reading the whole file

    OK you loser, I've edited it again and it should be OK now.
    Last edited by wossname; Jun 2nd, 2005 at 12:47 PM.
    I don't live here any more.

  8. #8
    Member
    Join Date
    May 2005
    Posts
    32

    Re: Extract thumbnail image from a file without reading the whole file

    Anyone have an example of how the use this code?

    I understand what it does I just wanted to see how others have used it.

    Thanks,

  9. #9

    Thread Starter
    l33t! MrPolite's Avatar
    Join Date
    Sep 2001
    Posts
    4,428

    Re: Extract thumbnail image from a file without reading the whole file

    lol an example?
    hmm lets see:
    VB Code:
    1. Dim imgPath As String = "C:\myImage.jpg"
    2. Dim img As Image
    3. img = GetThumbnail (imgPath)
    4.  
    5. ' If so then the image didn't have an embedded thumbnail
    6. If (img Is Nothing)
    7.     img = Image.FromFile (imgPath)
    8.     ' get thumbnail from image here...
    9.     img.Dispose()
    10. End If

    havent tested this. I just typed it in here
    rate my posts if they help ya!
    Extract thumbnail without reading the whole image file: (C# - VB)
    Apply texture to bitmaps: (C# - VB)
    Extended console library: (VB)
    Save JPEG with a certain quality (image compression): (C# - VB )
    VB.NET to C# conversion tips!!

  10. #10
    Member
    Join Date
    May 2005
    Posts
    32

    Re: Extract thumbnail image from a file without reading the whole file

    Quote Originally Posted by MrPolite
    lol an example?
    hmm lets see:
    VB Code:
    1. Dim imgPath As String = "C:\myImage.jpg"
    2. Dim img As Image
    3. img = GetThumbnail (imgPath)
    4.  
    5. ' If so then the image didn't have an embedded thumbnail
    6. If (img Is Nothing)
    7.     img = Image.FromFile (imgPath)
    8.     ' get thumbnail from image here...
    9.     img.Dispose()
    10. End If

    havent tested this. I just typed it in here
    I appreciate the response.

    Unfortunately my programming machine died this afternoon so I will have to give it a try after I recieve a new board or add visual studio to another machine.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width