对标记为ASCII的EXIF属性使用UTF8解码是否安全?

时间:2013-10-09 22:56:09

标签: c# .net gdi+ exif

我收到了一张带有EXIF ImageDescription元数据的图像文件,其值为“Test accents:éâäàè”。当使用.NET GDI +类提取此数据时,它会报告它以ASCII格式存储,但在使用ASCII解码器时会获得垃圾数据。通过反复试验,我发现我可以使用UTF8解码器正确提取它。

以下是示例代码:

public string GetDescription()
{
  const string filePath = @"C:\test_image.jpg";

  using (var bmp = new System.Drawing.Bitmap(filePath))
  {
    var propItem = bmp.PropertyItems.FirstOrDefault(p => p.Id == 270); // EXIF ImageDescription

    if (propItem == null)
      return null;

    string value = null;

    if (propItem.Type == 2) // ASCII
    {
      // Does not work: Returns "Test accents: ??????????"
      var asciiEnc = new System.Text.ASCIIEncoding();
      value = asciiEnc.GetString(propItem.Value, 0, propItem.Value.Length - 1);

      // CORRECT: Returns "Test accents: éâäàè"
      var utf8Enc = new System.Text.UTF8Encoding();
      value = utf8Enc.GetString(propItem.Value, 0, propItem.Value.Length - 1);
    }

    return value;
  }
}

我正在考虑更改我的生产代码,以便在提取元属性时始终使用UTF8解码器,即使PropertyItem.Type指示它是ASCII。它肯定适用于这种情况,但是如果我遗失了无法预料的后果,我会把它扔给你们。

那么 - 在提取ASCII元数据时使用UTF8解码器是个坏主意吗?

PS:我还尝试使用以下代码使用BitmapMetadata类提取数据,但结果不正确。如果有一种可靠的方法来使用这种技术,我愿意接受它。

// Returns incorrect string: "Test accents: éâäà è"
var value = bitmapMetadata.GetQuery("/app1/ifd/{ushort=270}") as string;

2 个答案:

答案 0 :(得分:7)

你无法让它变得可靠。 Exif遭受常见的编码苦难,Exif标准规定只应使用7位ASCII码,但每个人都忽略它。他们必须,ASCII只是无法正确编码多种语言的文本。非常了不起,Exif来自日本,这个国家的语言几乎没有使用ASCII和rich history编码问题。因此,每个人只需选择适合它们的任何编码,可以是UTF8,也可以是ANSI,无论代码页在创建映像时常用。

在岩石和硬地之间,使用UTF8编码是最佳选择。它不会很好地处理在ANSI代码页中编码的文本,你可以做的事情并不多。 Encoding.Default是一个糟糕的第二选择。您图像中的文本实际上是utf-8编码。

但是,如果文本实际上是纯ASCII,那么UTF8Encoding将正常工作。 Utf-8以相同的方式对ASCII码进行编码。

答案 1 :(得分:0)

IPTC standardIptc.Envelope.CharacterSet,因此在jbrout(在Python中)我们do

self._md["Iptc.Envelope.CharacterSet"] = ['\x1b%G', ]

当然我相信每个人都应该只将UTF8用于任何进入磁盘(或线路)的东西。使用ANSI编码(或者在Microsoft的其他操作系统中调用它)应该被视为违法行为。