获取 EXIF 方向标签,旋转到正确的方向,处理图像并以正确的方向保存图像

Posted

技术标签:

【中文标题】获取 EXIF 方向标签,旋转到正确的方向,处理图像并以正确的方向保存图像【英文标题】:Get EXIF Orientation Tag,Rotate to Proper Orientation, Process Image and Save the Image with proper Orientation 【发布时间】:2016-04-16 21:32:45 【问题描述】:

我的程序批量处理一些图像。我目前需要读取图像的 exif 方向标签,将其旋转到正确的方向,进行一些处理并保存图像,而不使用任何 EXIF 方向标签,但具有正确的旋转。(或带有正确方向的 EXIF 标签)

我正在阅读 EXIF 并使用 this library 旋转:

  var bmp = new Bitmap(pathToImageFile);
    var exif = new EXIFextractor(ref bmp, "n"); // get source from http://www.codeproject.com/KB/graphics/exifextractor.aspx?fid=207371

    if (exif["Orientation"] != null)
    
    RotateFlipType flip = OrientationToFlipType(exif["Orientation"].ToString());

    if (flip != RotateFlipType.RotateNoneFlipNone) // don't flip of orientation is correct
    
    bmp.RotateFlip(flip);
    bmp.Save(pathToImageFile, ImageFormat.Jpeg);
    

    // Match the orientation code to the correct rotation:

    private static RotateFlipType OrientationToFlipType(string orientation)
    
    switch (int.Parse(orientation))
    
    case 1:
    return RotateFlipType.RotateNoneFlipNone;

    case 2:
    return RotateFlipType.RotateNoneFlipX;

    case 3:
    return RotateFlipType.Rotate180FlipNone;
    case 4:
    return RotateFlipType.Rotate180FlipX;
    break;
    case 5:
    return RotateFlipType.Rotate90FlipX;
    break;
    case 6:
    return RotateFlipType.Rotate90FlipNone;
    case 7:
    return RotateFlipType.Rotate270FlipX;
    case 8:
    return RotateFlipType.Rotate270FlipNone;
    default:
    return 


这行得通。但是保存此图像时,exif 旋转标签仍然存在,这使图像方向错误。 我能做的是

       var bmp = new Bitmap(OS.FileName);       
       var exif = new EXIFextractor(ref bmp, "n");
       exif.setTag(0x112, "1");
       bmp.save("strippedexifimage");

但是当在循环中使用这段代码时,我的程序会减慢 50% 左右。还有其他方法吗?可能是应用旋转后反旋转图像的代码,这行得通吗?

更新:

@Hans Passant 您的答案有效,但它产生的结果与图书馆产生的结果相同。当我使用 bitmap.save() 时,库和您的代码都有效。但是当我使用以下代码根据用户选择的格式保存图像时。 Imgformat 可以是imgformat = "image/png";,imgformat = "image/jpeg"; 等,一些图像仍然会使用错误的 exif 方向标签保存。即:我在 Windows 资源管理器中看到错误的图像预览,当我用 MS Paint 打开图像时,图像的方向正确。我做错了什么?请帮忙。

private void saveJpeg(string path, Bitmap img, long quality)
        


            EncoderParameter qualityParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);


            ImageCodecInfo Codec = this.getEncoderInfo(imgformat);
             if (Codec == null)
              return;

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;    
            img.Save(path + ext, Codec, encoderParams);
        



 private ImageCodecInfo getEncoderInfo(string mimeType)
        
            // Get image codecs for all image formats
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        

【问题讨论】:

看看 ImageMagick。我认为它可以满足您的所有需求。您可以为它编写代码.. 或按原样使用它。 :) 【参考方案1】:
  var exif = new EXIFextractor(ref bmp, "n")

使用库来实现功能可以为您节省大量时间。否则,当库设计不佳或难以使用时,您会被困几天。 ref bmp 是第一个响亮的警报,您通过尝试将值指定为字符串而使其陷入绝望的深渊。这很有吸引力,因为您不必考虑在正确的 setTag() 重载中“类型”可能意味着什么。它是第 3 类,需要一个带有两个元素的 byte[]。这个是根本找不到的,只有在不需要的时候才能正确使用库。

放弃图书馆,它没有帮助。存储方向的 EXIF 标签的 id 为 0x112,编码为 16 位值。直接使用 System.Drawing 读取值并强制恢复为 1 即可。像这样:

static void FixImageOrientation(Image srce) 
    const int ExifOrientationId = 0x112;
    // Read orientation tag
    if (!srce.PropertyIdList.Contains(ExifOrientationId)) return;
    var prop = srce.GetPropertyItem(ExifOrientationId);
    var orient = BitConverter.ToInt16(prop.Value, 0);
    // Force value to 1
    prop.Value = BitConverter.GetBytes((short)1);
    srce.SetPropertyItem(prop);

    // Rotate/flip image according to <orient>
    switch (orient) 
        // etc...
    

【讨论】:

非常感谢。我搜索了是否有办法直接通过代码执行此操作,但找不到任何方法。orient 是否返回我的开关盒中的值(我的意思是 1 ,2,3..等) 呵呵我还记得在某个时候抓住了那个特定的库......然后把它扔掉并重写了我在规范中需要的部分。一如既往,汉斯的好建议! @atlaste 我有用于以不同格式保存图像的代码。我想保留代码,因为整个工作流程都依赖于它。当我使用 savejpeg 方法时出现错误。请问告诉我这里出了什么问题。 @techno 我猜缩略图看不到方向标签,或者它是缓存的效果(缩略图通常被缓存)。在软件中唯一可以确定的是,通过检查数据和规格,您没有犯错。第三方软件的行为方式......好吧,这不是您可以控制的。因此,除了“我会遵循规范”之外,您的问题没有很好的答案。 @atlaste 这不是缩略图缓存的问题。有一个名为exiv2.org 的实用程序我通过命令行使用它并从exiv2 rm myimage.jpg 等图像中删除所有exif 数据。一旦我这样做了我的程序产生的错误旋转的图像,回到原来的方向。我尝试将它合并到我的代码中。使用 exiv2 和库提取 exif 它使用我的程序的旧版本渲染图像的实际时间约为 34 秒需要 1 分钟以上。

以上是关于获取 EXIF 方向标签,旋转到正确的方向,处理图像并以正确的方向保存图像的主要内容,如果未能解决你的问题,请参考以下文章

EXIF 方向参数 Orientation

使用 Python 旋转具有 EXIF 中指定方向的图像,而不使用 PIL,包括缩略图

Chrome 图片 EXIF 方向问题

JQuery-File-Upload BlueImp文件上传EXIF方向旋转

exif-js 方向在 android 上总是返回 0 但在桌面上工作

Android图片处理:识别图像方向并显示