Meet us at PRINT 19. Chicago, IL. Oct. 3 - 5.
This documentation is for the old version. Go to the latest Graphics Mill docs

Loading Thumbnails from EXIF Metadata

Creating thumbnails from the image is very wide-spread task. A good example is a file browser application. User can preview content of image files without having to open them. However generating thumbnails for multiple files may seem to be too long to him. It is especially actual when they browse large images, such as high-resolution photos (which can be, say, 5 or more megapixels). If you use traditional thumbnailing technique (image is loaded into memory and then resized), you will find out that this method has quite low performance. It is especially noticeable when you try to create multiple thumbnails at a time. If you use more advanced technique, provider with LoadThumbnail method of the Bitmap class, it will increase the performance, but thumbnails quality will be quite low.

Fortunately if you are working with digital photos, there is a solution which solves all these problems - reading thumbnail from EXIF data.

All the modern cameras writes a block of data called EXIF when capturing an image. EXIF contains a number of camera parameters, as well as other details (some models can even write GPS information). Along with this data most cameras saves a thumbnail which is displayed at the LCD display of this camera. So to get a thumbnail for a photo we need not read entire bitmap into memory, we can just take predefined thumbnail.

Graphics Mill for .NET provides easy-to-use support to EXIF fields. This code demonstrates how to extract a thumbnail from the EXIF:

Visual Basic
Dim JpegReader As New Aurigma.GraphicsMill.Codecs.JpegReader("C:\IMG_0001.jpg")

Dim thumbnail As Aurigma.GraphicsMill.Bitmap = _
 JpegReader.Exif.Item(Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail)

JpegReader.Dispose()
C#
Aurigma.GraphicsMill.Bitmap thumbnail = null;

using (Aurigma.GraphicsMill.Codecs.JpegReader jpegReader =
           new Aurigma.GraphicsMill.Codecs.JpegReader(@"C:\IMG_0001.jpg"))
{
    thumbnail = (Aurigma.GraphicsMill.Bitmap)
        (jpegReader.Exif[Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail]);
}

The only shortcoming of this thumbnailing approach is that not each image file has EXIF data. More over, in some files containing EXIF data thumbnail may be absent. So to handle this situation we should combine both techniques.

Also there is a limitation - you will get a thumbnail of the size which is stored inside EXIF (typically 160x120). To get a thumbnail of another size, you should resize it additionally.

This code example contains improvements that resolve both problems:

Visual Basic
Const thumbnailSize As Integer = 120

Dim filePath As String = "C:\mountain.jpg"

Dim jpegReader As New Aurigma.GraphicsMill.Codecs.JpegReader(filePath)

Dim thumbnail As New Aurigma.GraphicsMill.Bitmap

If (Not jpegReader.Exif Is Nothing) AndAlso (jpegReader.Exif.Contains( _
 Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail)) Then
    thumbnail = jpegReader.Exif.Item(Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail)
End If

jpegReader.Dispose()

If Not thumbnail Is Nothing Then
    'Resize proportionaly
    If thumbnail.Width > thumbnail.Height Then
        thumbnail.Transforms.Resize(thumbnailSize, 0)
    Else
        thumbnail.Transforms.Resize(0, thumbnailSize)
    End If
Else
    thumbnail = New Aurigma.GraphicsMill.Bitmap
    thumbnail.LoadThumbnail(filePath, thumbnailSize, thumbnailSize)
End If
C#
const int thumbnailSize = 120;

string filePath = @"C:\mountain.jpg";

Aurigma.GraphicsMill.Bitmap thumbnail = null;

using (Aurigma.GraphicsMill.Codecs.JpegReader jpegReader =
           new Aurigma.GraphicsMill.Codecs.JpegReader(filePath))
{
    if ((jpegReader.Exif != null) && (jpegReader.Exif.Contains(
        Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail)))
    {
        thumbnail = (Aurigma.GraphicsMill.Bitmap)
            (jpegReader.Exif[Aurigma.GraphicsMill.Codecs.ExifDictionary.Thumbnail]);
    }
}

if (thumbnail != null)
{
    //Resize proportionaly
    if (thumbnail.Width > thumbnail.Height)
    {
        thumbnail.Transforms.Resize(thumbnailSize, 0);
    }
    else
    {
        thumbnail.Transforms.Resize(0, thumbnailSize);
    }
}
else
{
    thumbnail = new Aurigma.GraphicsMill.Bitmap();
    thumbnail.LoadThumbnail(filePath, thumbnailSize, thumbnailSize);
}