Results 1 to 10 of 10

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

Threaded View

  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!!

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