读取 JPEG 元数据(方向)时出现问题

问题描述 投票:0回答:6

我有一张用 iPhone 拍摄的 JPEG 图像。在我的台式电脑(Windows 照片查看器、Google Chrome 等)上,方向不正确。

我正在开发一个 ASP.NET MVC 3 Web 应用程序,我需要上传照片(当前使用 plupload)。

我有一些服务器端代码来处理图像,包括读取 EXIF 数据。

我尝试读取 EXIF 元数据中的

PropertyTagOrientation
字段(使用 GDI -
Image.PropertyItems
),但该字段不存在。

所以它要么是一些特定的 iPhone 元数据,要么是其他一些元数据。

我使用了另一个工具,例如 Aurigma Photo Uploader,它可以正确读取元数据并旋转图像。它是如何做到这一点的?

有谁知道哪些其他 JPEG 元数据可以包含 Aurigma 使用的需要旋转的信息?

这是我用来读取 EXIF 数据的代码:

var image = Image.FromStream(fileStream);

foreach (var prop in image.PropertyItems)
{
   if (prop.Id == 112 || prop.Id == 5029)
   {
      // do my rotate code - e.g "RotateFlip"
      // Never get's in here - can't find these properties.
   }
}

有什么想法吗?

c# image-processing metadata jpeg gdi
6个回答
154
投票

这是解决 8 个方向值的代码片段。

首先一些注意事项:

EXIF id 0x0112 用于方向。这是一个有用的 EXIF id 参考 http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html

0x0112274 的十六进制等效值。

PropertyItem.Id
的数据类型是
int
,这意味着 274 在这里有用。

此外,5029可能应该是0x502920521,这与缩略图方向相关,尽管这可能不是这里想要的。

东方影像:

注意:

img
System.Drawing.Image
或继承自它,如
System.Drawing.Bitmap

if (Array.IndexOf(img.PropertyIdList, 274) > -1)
{
    var orientation = (int)img.GetPropertyItem(274).Value[0];
    switch (orientation)
    {
        case 1:
            // No rotation required.
            break;
        case 2:
            img.RotateFlip(RotateFlipType.RotateNoneFlipX);
            break;
        case 3:
            img.RotateFlip(RotateFlipType.Rotate180FlipNone);
            break;
        case 4:
            img.RotateFlip(RotateFlipType.Rotate180FlipX);
            break;
        case 5:
            img.RotateFlip(RotateFlipType.Rotate90FlipX);
            break;
        case 6:
            img.RotateFlip(RotateFlipType.Rotate90FlipNone);
            break;
        case 7:
            img.RotateFlip(RotateFlipType.Rotate270FlipX);
            break;
        case 8:
            img.RotateFlip(RotateFlipType.Rotate270FlipNone);
            break;
    }
    // This EXIF data is now invalid and should be removed.
    img.RemovePropertyItem(274);
}

17
投票

您似乎忘记了您查找的方向 id 值是十六进制的。在使用 112 的地方,应该使用 0x112。

这篇文章解释了Windows如何调整方向处理,并且这个似乎与您正在做的事情非常相关。


14
投票

这篇文章看来你需要检查ID 274

foreach (PropertyItem p in properties) {
      if (p.Id == 274) {
            Orientation = (int)p.Value[0];
         if (Orientation == 6)
            oldImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
         if (Orientation == 8)
            oldImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
      break;
      }
}

14
投票

我结合了给出的答案和评论,得出了这个:

    MemoryStream stream = new MemoryStream(data);
    Image image = Image.FromStream(stream);

    foreach (var prop in image.PropertyItems) {
        if ((prop.Id == 0x0112 || prop.Id == 5029 || prop.Id == 274)) {
            var value = (int)prop.Value[0];
            if (value == 6) {
                image.RotateFlip(RotateFlipType.Rotate90FlipNone);
                break;
            } else if (value == 8) {
                image.RotateFlip(RotateFlipType.Rotate270FlipNone);
                break;
            } else if (value == 3) {
                image.RotateFlip(RotateFlipType.Rotate180FlipNone);
                break;
            } 
        }
    }

2
投票

在这里发帖以防万一有人遇到同样的问题。我在使用 WFP 和 GDI 读取方向的生产中遇到问题。唯一有效的是使用:https://github.com/dlemstra/Magick.NET

代码相当简单:

var img = new MagickImage(inputStream);
img.AutoOrient();   // Fix orientation
img.Strip();        // remove all EXIF information
img.Write(outputPath);

0
投票

我采用了 ReenignE 答案,将其作为扩展,但我没有删除属性 274,而是将其设置为 1(= 水平(正常))

public static Image AutoOrientation(this Image image)
{
    // The EXIF id 0x0112 is for Orientation.
    // This is a helpful EXIF id reference http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
    // 0x0112 is the hex equivalent of 274.
    const int EXIF_Orientation = 0x0112; //274

    if (Array.IndexOf(image.PropertyIdList, EXIF_Orientation) > -1)
    {
        var orientationProperty = image.GetPropertyItem(EXIF_Orientation);
        var orientation = (int)orientationProperty.Value[0];
        switch (orientation)
        {
            case 1:
                // No rotation required.
                break;
            case 2:
                image.RotateFlip(RotateFlipType.RotateNoneFlipX);
                break;
            case 3:
                image.RotateFlip(RotateFlipType.Rotate180FlipNone);
                break;
            case 4:
                image.RotateFlip(RotateFlipType.Rotate180FlipX);
                break;
            case 5:
                image.RotateFlip(RotateFlipType.Rotate90FlipX);
                break;
            case 6:
                image.RotateFlip(RotateFlipType.Rotate90FlipNone);
                break;
            case 7:
                image.RotateFlip(RotateFlipType.Rotate270FlipX);
                break;
            case 8:
                image.RotateFlip(RotateFlipType.Rotate270FlipNone);
                break;
        }
        orientationProperty.Value[0] = 1; //set it to 1 = Horizontal (normal)
        image.SetPropertyItem(orientationProperty);
    }

    return image;
}
© www.soinside.com 2019 - 2024. All rights reserved.