并非所有使用Image.PropertyItems检索的图像属性

时间:2014-02-27 23:26:38

标签: c# .net image exif

我正在尝试获取给定图像中所有EXIF标记的列表。 使用Image.propertyItems[]数组,我可以枚举图像对象实例读取的所有项目,并输出它们的ID。

我看到有些项目没有列在那里,包括Windows资源管理器在内的其他应用程序似乎没有问题检索。

E.G。在以下代码中......

Image img = new Bitmap("C:\\IMAG0648.jpg");
foreach (PropertyItem property in img.PropertyItems)
  {
    Trace.WriteLine(property.Id);
  }

我得到了大多数项目的列表,特别是虽然我遗漏了0x010F0x0110(可能还有其他人)。我知道这些项因为我可以在另一个EXIF编辑器(如PhotoME)中打开相同的图像,它们显然在那里,并且清楚地标记为正确的ID。

EXIF中是否存在嵌套级别,而且我没有走得太远,或者是否有某些原因导致上述基本形式不起作用?

2 个答案:

答案 0 :(得分:2)

尝试ExifLib - 有一个带源代码的演示项目,可以从您可以使用的图像中提取所有标记。

编辑:我将附上我的答案来解释为什么我认为.Net Image类不能像我们预期的那样处理所有EXIF标记。但是,我将在上面留下我的初步链接和建议,因为我认为它最终是最好的选择。

好的,关于为什么

我在下面描述的测试使用了Windows 7显示制作和模型的EXIF数据的图像(通过右键单击文件>属性>'详细信息'选项卡>'相机'部分),但在.Net中{{1不包含这些相同的EXIF标记。在另一个答案中提到了使用HTC One拍摄的图像,因此我找到了满足我的测试here的图像。 (具体来说,我从这个网页上使用了原版2.jpg,原版4.jpg和原版8.jpg。)

首先,我看了PropertyItems并得到了32.所以那里有数据! (显然,我们知道Windows 7在我的情况下会看到EXIF标签)。但是,当我遍历img.PropertyItems.Count()并查看每个.PropertyItems时(根据您原来的问题):

  • 我得到32个结果
  • 我没有得到271(0x010F - 相机制造)或272(0x0110 - 相机型号)的ID
  • 我确实得到了282,283,296,305,306和27个其他5位数字ID
  • 如果我使用Id我会获得SoftwareUsed(或者如果我使用206,我会获得DateTime)EXIF属性

那么,到目前为止,为什么.Net Image类没有看到ID为271/272的EXIF标签(同样是Camera Make / Model)?

我深入研究了ExifLib的源代码(回答顶部的链接)并认为我看到了正在发生的事情:

  • 如果查看ExifReader.cs中的img.PropertyItems.Single(x => x.Id == 305).Value方法(第655行),您会看到字节偏移用于查找“Exif IDF”和每个标记的总空间
  • 此方法返回特定的字节数组,然后将其转换为正确的数据类型
  • 如果该类型是ASCII字符串 - 删除空字符并调整日期格式

因此,当不是任何字节偏移时,.Net Image类似乎能够通过private byte[] GetTagBytes(...)正确返回EXIF标记。

使用ExifDataView(http://www.nirsoft.net/utils/exif_data_view.html)我能够验证这一点:

  • 我发现我总是能够使用.Net在值长度为4(“HTC”+空字符)时正确检索Make和Model
  • 当长度为5(“HTC”+ null + null?)时,我从不能够使用.Net
  • 在我上面的测试中(使用原始的4.jpg图像),SoftwareUsed和DateTime标签有效,因为这些标签的长度为(字符串长度)+ 1为空字符。 Camera Make标签长度为(字符串长度)+ 2并且不起作用。这似乎抛弃了一切。

ExifLib代码正确处理这些偏移和/或多个空字符,而.Net则没有。

结果是.Net Image类不会作为PropertyItems的一部分迭代这些属性,并在使用PropertyItems时返回'Sequence contains no matching element'

底线:如果您希望正确处理所有图像,请使用ExifLib或其他一些专门用于处理提取EXIF数据的第三方库。如果你希望它在字节恰到好处的某些时候工作,请使用.Net Image类: - )

答案 1 :(得分:1)

根据the documentation,您指定的标签肯定存在。这对this sample image

有用

Sample image with EXIF metadata

int tagMake = 0x010F;  // 271
int tagModel = 0x0110; // 272

Image image = Image.FromFile(@"C:\image.jpg");

byte[] make = image.PropertyItems.Single(x => x.Id == tagMake).Value;
byte[] model = image.PropertyItems.Single(x => x.Id == tagModel).Value;

var encoding = new System.Text.ASCIIEncoding();

Console.WriteLine(encoding.GetString(make));  // Returns: Canon
Console.WriteLine(encoding.GetString(model)); // Returns: Canon PowerShot S40