It's been awhile since I wrote a how to post, so here goes one taken from my latest little side project.
How to find the date a picture was taken [DateTimeOriginal] from the EXIF1 metadata using C#.
I discovered that the EXIF data is a bit of work to get to. It's not just a matter of instantiating an object off of the picture (jpg, bmp, etc.) and picking out the property you want based on the name. Oh no, that would be way too easy. There are some hoops to jump through.
Actually, the EXIF values are stored in the Image.PropertyItems collection, but the properties are all stored based on an ID without any immediate reference to the name. So you have to know the ID of the tag you're looking for. I found this list mapping tag ID to property name. The DateTimeOriginal property ID is 0x9003. Um yeah, that's a hexadecimal value, meanwhile the PropertyItems ID property uses an integer value. That means you have to convert the hex value to an integer, like so [must remove the 0x prefix]:
int id = int.Parse("9003", System.Globalization.NumberStyles.AllowHexSpecifier);
Now that we have the integer representation, we can grab the PropertyItem out of the collection:
PropertyItem prop = img.GetPropertyItem(id);
Here's another interesting little twist... The PropertyItem.Value is stored as a byte array. So now you have to convert that byte array in to something useful. I chose to first convert it to a string from which I could later manipulate it into a DateTime object. Fortunately, .NET provides the Encoding class with the ASCII property that makes this a trivial thing to do [thanks Sahil!]:
byte[] asciiBytes = prop.Value; string strDate = System.Text.Encoding.ASCII.GetString(asciiBytes);
Now we encounter another little twist. The string comes out in a format like "YYYY:MM:DD HH:MM:SS" which would be "2007:06:06 19:43:31". Notice that the year, month and day are separated by a colon [":"] instead of a dash ["-"] or forward slash ["/"]. That means we have to first replace those colons with forward slashes before we can convert it to a DateTime object:
DateTime dateCreated = new DateTime(); // Pull out the year, month, day and time individually from the string string dateYear = date.Substring(0, 4); string dateMonth = date.Substring(5, 2); string dateDay = date.Substring(8, 2); string dateHourMinSec = date.Substring(11, 8); // Create a stringbuilder that is formatted for conversion to DateTime StringBuilder sbDateCreated = new StringBuilder(); sbDateCreated.Append(dateMonth + "/"); sbDateCreated.Append(dateDay + "/"); sbDateCreated.Append(dateYear + " "); sbDateCreated.Append(dateHourMinSec); // Convert the string to DateTime dateCreated = Convert.ToDateTime(sbDateCreated.ToString());
VoilĂ , you now have a DateTime object that represents the date and time the picture was originally taken. And here is a class for a console application if you want to see it all put together [and even compile it yourself]: GetDateTaken.cs.txt [right-click -> save target as...]
While working on this I came across Reading EXIF Tags From JPEG Files at VBAccelerator.com which goes into quite a bit more depth and also provides some nice sample code in the downloadable project.
Hope that helps!
~tod
DISCLAIMER: As usual, my standard code disclaimer applies and I welcome all suggestions for improvement.
1EXIF (exchangeable image file format) is a specification for the image file format used by digital cameras that stores the properties of an image such as date/time taken, ISO speed, camera manufacturer, camera model, flash, resolution and many, many others.
Email or RSS 1.0, RSS 2.0 & Atom