Bitmap Coding and Metatdata in WPF
Written by Administrator   
Wednesday, 10 February 2010
Article Index
Bitmap Coding and Metatdata in WPF
Coding bitmaps
Reading metadata
Writing metadata

Reading metadata

The only complication with coding and decoding and generally working with sophisticated image file formats is metadata.

The metadata for each frame is stored in its metadata property and there is also a global metadata property associated with the decoder/encoder in the case of a multiframe format. You can check what metadata is stored with any particular image file by right-clicking on it and selecting Properties.

To use the metadata associated with a file that you have read in there are a number of different possible techniques.

Banner

The Metadata property returns an ImageMetadata type but this is really just the base type for all metadata objects. To make use of it you have to cast it to something more specific - and for bitmap formats this is a BitmapMetadata type:

 BitmapMetadata MyMeta = (BitmapMetadata)
 MyJpegDec.Frames[0].Metadata;

The BitmapMetadata type has a range of predefined properties that correspond to the more common EXIF, text, IFD, IPTC and XMP metadata - the sort of metadata that is generally added by a digital camera, for example. To retrieve the camera manufacturer you would use something like:

string data =MyMeta.CameraManufacturer;

You can look up the range of predefined properties in the documentation. You can use the Keywords property to return a collection of any keywords that have been assigned to the image in an attempt to classify it.

Metadata Query Language

The problem with metadata, even EXIF or other defined metadata is that there are custom and extension properties for which BitmapMetadata just doesn't have properties defined. The solution to this difficulty is the GetQuery method. This performs a query using the special Metadata Query Language (MQL). The basic idea is that you provide a path that indicates where the metadata is stored and a specification of the metadata item to be retrieved.

The path part of the specification corresponds to the application or the standard used to write the data. Metadata in a single file can be generated by a number of different applications or to correspond to different standards. For example, you could have a metadata block written as an EXIF block and an XMP block all associated with a single file.

There can even be multiple blocks of the same type and these are referred to using an index notation. Each block could have a metadata item - name and value pair - with the same name. That is, there could be multiple "author" fields each within a different metadata block. Once you realise that metadata has multiple sources and formats you begin to understand the need for MQL and its form.

MQL may be logical but the big problem is finding out the paths and names that correspond to the properties you need. These in principle are standard but many of the items of data that you might expect to be standard are manufacturers' extensions and these are kept secret and vary from manufacturer to manufacturer. As a result trying to work with photo meta data is a frustrating task.

You can discover what properties are stored in a metadata block by querying it. For example, for a JPEG there are five metadata blocks corresponding to the paths:

  /app0
/app1
/app1/ifd
/app1/ifd/exif
/xmp

If you query /app1 using:

 object data = MyMeta.GetQuery(@"/app1");

then you will discover that data is a query object with two results corresponding to tag codes 0 and 1 which in turn correspond to the ifd block and the ifd/exif block.

If you query the ifd/exif block using:

 object data = MyMeta.GetQuery(
@"/app1/ifd/exif");

you will find that there are 18 or more tag codes and you can look these up in the exif documentation, http://www.exif.org. For example, tag code 33437 gives the f number that the photo was taken at. You can retrieve this raw data using:

 object data = MyMeta.GetQuery(
@"/app1/ifd/exif/{ushort=33437}");

Your work isn't over however when you have retrived it. For one thing the type may be stated as ushort but what is returned is two ushorts concatenated as a single ulong. The reason for this apparently odd behaviour is that the property is a rational defined in the specification as two longs - the first is the numerator and the second the denominator. Thus:

 data= 0x0000000a0000001c

translates to 28/10 or f/2.8.

Instead of using absolute metadata query language paths, you can use a policy component path. For example, for author the path is "System.Author". When the metadata query engine sees this type of query, it hands this off to the policy component. In turn, the policy component returns a fully qualified metadata query language string back. If a file has the information requested in more than one location it's the policy component's job to determine which fully qualified path to actually use. You can find out what Metadata Policies are provided in the documentation for the Windows Imaging component which is what WPF bases its image class on.

For example to get the f number using the policy resolution system you would use:

 object data = MyMeta.GetQuery
(@"System.Photo.Aperture");

This returns a double that isn't necessarily exactly equal to the previous F number retrieved as a rational value.

<ASIN:0596102453>

<ASIN:1933988223>

<ASIN:0321374479>

<ASIN:0596510373>



Last Updated ( Friday, 19 March 2010 )