Reading EXIF and Other Image Properties Using GDI+
Complete access to EXIF and TIFF Image tags.
Many digital cameras record information about when and how a picture was taken using the EXIF format (which is slowly becoming the DCF format under ISO). You can read and write this information using GDI+; not just that but you can also read the image metadata from TIF and PNG files.
About EXIF Tags
EXIF tags are an extension of the JPEG format used to store particular information about the make and model of a camera, when a picture was taken and digitised, information about the resolution of the image and things like the exposure time, focal length and whether a flash was used to take the photo.
if you're interested in the details of EXIF then read TsuruZoh Tachibanaya's Description of Exif file format which goes through most of the EXIF tags and exactly how they are stored.
GDI+ provides a PropertyItem class that contains details of meta-data associated with an image. This covers all types of image meta-data, and not just EXIF, so you can also use it to investigate information stored in TIF and PNG files too.
Meta-data and particularly EXIF tags have different storage formats defined to allow multiple types of data to be stored. For example, the camera model is stored as ASCII, whilst the things like the focal length are stored as a series of rational (basically a fraction; one value stores the numerator and the other the denominator) value.
The GDI+ PropertyItem class shirks any responsibility for decoding this information and simply presents you with a pointer to an area of memory containing the data. This sample demonstrates how to decode the basic types and thus display and use the information.
Reading EXIF Tags
The GDI+ Wrapper provides the following properties and methods as part of the GDIPImage class for reading and manipulating the EXIF tags and meta data of an Image:
The GDIPPropertyItem class provides methods to read and manipulate properties of an item. A property item consists of an ID (one of the PropertyTag enumeration values, a Type (one of the PropertyTagType enumeration values), the Length (which is the total size of the binary data associated with the tag) and the data for the tag that is stored as a byte array. The Name property provides a lookup between the item's ID and a text string specifying its name.
To make it easier to use the data, a number of helper methods are provided for interpreting the data. The following table demonstrates how to use the helper methods to convert the byte data into a more usable form:
With this information, you can now start working with the EXIF values. The code used in the sample to render the EXIT tags is as follows:
Private Sub showEXIFTags(img As GDIPImage) Dim i As Long Dim sItem As String Dim prop As GDIPPropertyItem Dim j As Long Dim v As Variant Dim s As String For i = 1 To img.PropertyCount Set prop = img.PropertyItem(i) sItem = prop.Name & " " Select Case prop.ItemType Case PropertyTagTypeASCII sItem = sItem & prop.ParseString() Case PropertyTagTypeRational, PropertyTagTypeSRational For j = 1 To prop.ValueCount If (j > 1) Then sItem = sItem & ", " End If v = prop.ParseRational(j) sItem = sItem & v(1) & "/index.html" & v(2) Next j Case PropertyTagTypeLong For j = 1 To prop.ValueCount If (j > 1) Then sItem = sItem & ", " End If sItem = sItem & prop.ParseLong(j) Next j Case PropertyTagTypeShort For j = 1 To prop.ValueCount If (j > 1) Then sItem = sItem & ", " End If sItem = sItem & prop.ParseShort(j) Next j Case PropertyTagTypeUndefined ReDim b(0 To prop.ValueCount - 1) As Byte prop.GetData b For j = 1 To prop.ValueCount - 1 If (j > 1) Then sItem = sItem & " " End If s = Hex(b(j - 1)) If Len(s) = 1 Then s = "0" & s sItem = sItem & s Next j Case Else sItem = sItem & prop.ItemType & " " & prop.Length End Select lstEXIFTags.AddItem sItem Next i End Sub
Of course, there's more you can do to make this user friendly. For example, the dates used for the time the photo was taken and digitised are provided in ISO format as a string. You can easily convert this to a DateTime:
Public Function ISODateTimeToDate( _ ByVal isoDateTime As String _ ) As Date Dim dDate As Date dDate = DateSerial( _ Mid(isoDateTime, 1, 4), _ Mid(isoDateTime, 6, 2), _ Mid(isoDateTime, 9, 2)) + _ TimeSerial( _ Mid(isoDateTime, 12, 2), _ Mid(isoDateTime, 15, 2), _ Mid(isoDateTime, 18, 2)) ISODateTimeToDate = dDate End Function
Another example is the Flash value (PropertyTagExifFlash = &H9209&). This is returned as an integer, but referring to the EXIF Tag Description document we see the available values are: