I am trying to get a list of all the EXIF
tags in a given image.
using the Image.propertyItems[]
array, I can enumerate all of the items that instance of the image object reads, and output their ID.
I see there are items that ARE NOT listed there, that other applications including windows explorer seem to have no issue retrieving.
E.G. in the following code...
Image img = new Bitmap("C:\\IMAG0648.jpg");
foreach (PropertyItem property in img.PropertyItems)
{
Trace.WriteLine(property.Id);
}
I get a listing of most of the items, specifically though I am missing (among possibly others) the 0x010F
and 0x0110
. I know these items are there because I can open the same image in another EXIF editor like PhotoME, and they are clearly there, and clearly labeled as the correct ID.
Are there nesting levels in the EXIF
and I am not walking out far enough, or is there some reason this would not work in its basic form above?
Try ExifLib - there is a demo project with source that extracts all tags from an image that you could use.
Edit: I'm going to append my answer to explain why I believe the .Net Image class doesn't handle all EXIF tags as we might expect. However, I'm going to leave my initial link and suggestion above as I believe it's the best option in the end.
Ok, on to the Why:
My testing described below used images where Windows 7 showed EXIF data for make and model (by right clicking on file > Properties > 'Details' tab > 'Camera' section), but in .Net the PropertyItems
do not contain these same EXIF tags. Images taken with the HTC One were mentioned in another answer, so I found images that satisfy my test here. (Specifically, I used original-2.jpg, original-4.jpg, and original-8.jpg from this webpage.)
First, I looked at img.PropertyItems.Count()
and got 32. So there is data in there! (Clearly, we know Windows 7 in my case is seeing the EXIF tags). But, when I iterate over the .PropertyItems
and look at each Id
(per your original question):
img.PropertyItems.Single(x => x.Id == 305).Value
I do get the SoftwareUsed (or if I use 206 I get the DateTime) EXIF propertySo, to your point, why is the .Net Image class not seeing the EXIF tags with Ids of 271/272 (again, Camera Make/Model)?
I dug into ExifLib's source code (link at top of answer) a little bit and think I see what's happening:
private byte[] GetTagBytes(...)
method in ExifReader.cs (line 655) you'll see that byte offsets are used to find the 'Exif IDF' and total space per tagSo it would seem that the .Net Image class is able to return the EXIF tag properly via PropertyItems
when there aren't any byte offsets in play.
Using ExifDataView (http://www.nirsoft.net/utils/exif_data_view.html) I was able to validate this:
The ExifLib code handles these offsets and/or multiple null characters correctly and .Net does not.
The result is the .Net Image class doesn't iterate over these properties as part of PropertyItems
and returns a 'Sequence contains no matching element' when using image.PropertyItems.Single(x => x.Id == tagMake).Value
Bottom line: use ExifLib or some other 3rd party library designed to handle extracting EXIF data if you want to it work on all images properly. Use the .Net Image class if you want it to work some of the time when the bytes are just right :-)