June 11, 2006

Retrieving "Date Taken" EXIF Metadata From a JPG

For the most part the GDI+ API in the .NET Framework 2.0 is powerful enough to match almost any image related challenge. However, I encountered some functionality that I found to be lacking in regards to how EXIF embedded metadata is retrieved from JPG files. My goal was to get the "Date Taken" property from an image using C#.

Unfortunately each slice of the image's metadata (AKA the PropertyItem object) can only be retrieved using a rather unintuitive integer-based ID look up. For example, you have to know that the "Date Taken" information can be accessed using a PropertyItem ID of 36867. Perhaps an enumeration of these IDs will be added to a future version of the Framework to help make this task easier for programmers? Justin Rogers made such an object available here to help folks out in the meantime.

Once the "Date Taken" PropertyItem has been defined we still run into problems after decoding it to a UTF8 string. To have the most flexibility in addressing this information it would be ideal to convert it to a DateTime object. However, the PropertyItem string value is decoded in a "YYYY:MM:DD HH:MM:SS" format. Sadly, the colons between the year and the month and the month and the day throw off both the Convert.ToDateTime() and DateTime.Parse() methods.

I've listed the GetDateTaken() method below as an example of the remaining string manipulation necessary to complete this task:

public DateTime GetDateTaken(Image targetImg)
{
//Property Item 36867 corresponds to the Date Taken
PropertyItem propItem = targetImg.GetPropertyItem(36867);
DateTime dtaken;

//Convert date taken metadata to a DateTime object
string sdate = Encoding.UTF8.GetString(propItem.Value).Trim();
string secondhalf = sdate.Substring(sdate.IndexOf(" "), (sdate.Length - sdate.IndexOf(" ")));
string firsthalf = sdate.Substring(0, 10);
firsthalf = firsthalf.Replace(":", "-");
sdate = firsthalf + secondhalf;
dtaken = DateTime.Parse(sdate);
return dtaken;
}

6 comments:

Anonymous said...

Hey..Thanks for this piece of information. I was wondering if I could get the the Ids for the remaining fields of an image. Metadata like Author,Exposure time etc.

Tron5000 said...

Yes, it's my understanding that you'd simply use a different ID for the PropertyItem you're interested in. As mentioned in the post, this page has a nicely organized enumeration of these IDs.

SID said...

thanks a lot buddy..

Unknown said...

I realize that it has been a long time since this was written, but I found it, so this might help someone else. But first, thanks for this post, I am happy it was so easy to get the date taken :)
But, you don't have to do all that work. (Maybe in .net 1.1, but not in 2.0 or later) You can parse the date with:

DateTime.ParseExact( Encoding.ASCII.GetString(propItem.Value), "yyyy:MM:dd HH:mm:ss\0", null);

where propItem is the property from the image.

the date string I was using always had the trailing byte 0, so that is why I included the "\0". I don't know if that will be there for EVERY image.

Anonymous said...

Fantastic. Simply fantastic. And in so few words.

Machtyn said...

I know this is a REALLY old post. But it was exactly what I was looking for. Fortunately or unfortunately, I found the sledgehammer before I found this hammer.

However, the sledgehammer also came with this page:
Retrieving Meta Data from JPEG Files Using C#. On this page he has a link to a file called GDIConstants.zip. In the zip is a file called GDIConstants.cs which contains a enum of all the EXIF data. I hope this provides a better resource than your original link.