EXIF Tags in C#

… or “Just how difficult can it be to store metadata in a file”.

Some images – especially JPGs – can contain extended metadata. For example, if the image is from a camera then the camera manufacturer, exposure, focal length, flash details and such may well be added as metadata. This practice has been going on form many, many years, in fact it was implemented in the last century so as its now nearing the end of 2013 as I write this, and we are at least as far as .NET 4.5 I guess accessing the metadata will be a doddle, so there’s no reason to write a blog entry about it.

See ya !

[Some time later, a sigh accompanied by a muttered "un-fricken'-believable"]. OK [cracks knuckles], lets do this.

Image myImage = Image.FromBitmap(@"C:\myImage.jpg");

// Start looking at the exif tags, which are PropertyItems
foreach(PropertyItem item in myImage.PropertyItems)
{
    // er ...
}

Let me explain the “er”. PropertyInfo contains four items:

Id A 16-bit ID number of the property
Value The associated value … as a byte array!
Length The number of bytes in the array
Type How the value should be interpreted (string, int, time/date, etc)

Modifying Tags (PropertyInfos)

You can change existing tags “simply” by accessing the appropriate PropertyInfo item for the item , change its value and save the image again. But at this point, alarm bells rang as I thought that the (jpeg) image would be re-compressed and hence loose quality – especially after reading this article duplicated here - but Microsoft (bless them) have been clever enough to keep the original jpeg bytes. So, why the articles I linked to ? Well, I did notice that loading and immediately saving a JPEG reduced its file size, however I also noticed it lost some of its original tags in the process ! Loading both “before” and “after” images into PaintShop pro and generating a difference image from the two proves the images are identical. (If you want to repeat the test, be sure to crank the gamma correction up to max so as to amplify any tiny changes there might be). Then again, those articles date back to 2003, pre-dating the .NET 2 I used for test purposes.

Adding New Tags

On first sight, TOUGH ! Image.PropertyItems provides no functions to add or insert new items, and even if it did the fact that the PropertyItem class itself is a sealed class that exposes no constructors would make it a bit of a bugger. Drats, and double drats!

Well, I toyed with the idea of using reflection etc to hack a new instance but then it occurred to me that PropertyItem instances will be created when you open a suitable file. So, what we do is open a second dummy file, hack one of its PropertyInfo entries to generate the data we want to create and then add it to our original image !

exif1

Note that strings stored in item.Value need to be null terminated, hence the ‘\0′ on the end of “Hello World”.

Better still, take dummy.jpg and embed it as a resource, that is add it as a project item, set its properties to embedded and read it using:

exif2

Now you may be asking where I got the item.id value of 0×9286 from. Well, by looking at a few example images from different professional image editors. Not ideal, but even the list on Microsoft’s website is a bit lacking.

Adding thumbnails can be a bit more involved as this chap found out , but the key to this one seems to be that thumbnail images must not exceed 160×160 pixels and must have the same aspect ratio as the main image.

Summary

  • Read tags requires a fair bit of code – fortunately a few good third party classes now exist such as the tag reading library that can be found on CodeProject.
  • You can modify existing tags.
  • New tags must be bodged in.
  • You can’t add or modify a tag without recompressing the image.

 

One comment

  1. Scotty says:

    This page was extremely helpful in working with some metadata in image files for a friend’s business. I was at a loss, but your work here helped tremendously. Thank you!

Leave a Reply