【问题标题】:Getting correct Image rotation [duplicate]获得正确的图像旋转[重复]
【发布时间】:2020-02-28 16:22:13
【问题描述】:

我有一个简单的问题:当我将图像加载到 Windows 窗体 PictureBox 时,有些图片会旋转,而有些则不会。

基本上,用户选择带有OpenFileDialog 的图片以及当图片被选中时:

private void OpenFD_FileOk(object sender, CancelEventArgs e)
{
    Image image = Image.FromFile(openFD.FileName);
    PB_profile.Image = image;
}

是的,我检查了原始图像旋转

编辑:
我将PictureBox 属性SizeMode 更改为StretchImage

【问题讨论】:

  • 你的意思是一些图片(不改变原始图像旋转)上传时旋转了 90 度,例如从原始旋转位置?
  • @P.Pat 是的,有时甚至是 180°

标签: c# image rotation


【解决方案1】:

来自相机的图片可以包含所谓的 EXIF 元数据。这个 EXIF 元数据可以有一个“方向”标签,许多图像查看程序会在显示图片时查看并相应地旋转图片。但是图像数据本身的方向保持不变。 因此,如果您的图像来自相机并且横向图像受到您所描述的影响,则很可能是 EXIF 方向标签。 This is an article 关于这个标签。 也许有 C# 代码可以帮助您处理 EXIF 标签,我没有检查。

【讨论】:

    【解决方案2】:

    如果图片包含exif dataPropertyItems应该包含orientation标签。

    它编码正确显示图像所需的旋转/翻转:

    PropertyTagOrientation

    按行和列查看图像方向。

    标记 0x0112

    1 - 第 0 行位于顶部 视觉图像,第0列是视觉左侧。
    2 - 第 0 个 行位于图像的可视顶部,第 0 列是 视觉右侧。
    3 - 第 0 行位于可视底部 图片,第0列是视觉右侧。
    4 - 第 0 行 位于图像的视觉底部,第 0 列是视觉 左侧。
    5 - 第 0 行是图像的视觉左侧,并且 第 0 列是视觉顶部。
    6 - 第 0 行是视觉右侧 图像的一侧,第 0 列是视觉顶部。
    7 - 第0个 行是图像的视觉右侧,第 0 列是 视觉底部。
    8 - 第 0 行是图像的视觉左侧, 第0列是视觉底部。

    这是一个检索PropertyItem的函数:

    PropertyItem getPropertyItemByID(Image img, int Id)
    {
      return 
        img.PropertyItems.Select(x => x).FirstOrDefault(x => x.Id == Id);
    }
    

    以下是使用 GDI+ RotateFlip 方法动态调整图像的示例:

    void Rotate(Bitmap bmp)
    {
        PropertyItem pi = bmp.PropertyItems.Select(x => x)
                             .FirstOrDefault(x => x.Id == 0x0112);
        if (pi == null) return; 
    
        byte o = pi.Value[0];
    
        if (o==2) bmp.RotateFlip(RotateFlipType.RotateNoneFlipX);
        if (o==3) bmp.RotateFlip(RotateFlipType.RotateNoneFlipXY);
        if (o==4) bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
        if (o==5) bmp.RotateFlip(RotateFlipType.Rotate90FlipX);
        if (o==6) bmp.RotateFlip(RotateFlipType.Rotate90FlipNone);
        if (o==7) bmp.RotateFlip(RotateFlipType.Rotate90FlipY);
        if (o==8) bmp.RotateFlip(RotateFlipType.Rotate90FlipXY);
    }
    

    它将图像更改为正确旋转的版本..

    我已经用this nice set of sample images 测试了值。

    注意:代码仅在图像实际包含方向标签时才有效。如果他们不这样做,可能是因为他们是扫描,那么它将什么都不做

    注2你写的我检查了原始图像旋转。这不是那么简单:资源管理器将显示已经旋转的图像,所以在这里它们看起来都正确并且即使检查属性也不会显示方向!

    通常,当不存在 exif 数据时,PropertyTagOrientation 标签存在,但只有默认值 1..

    更新: 如果图片没有PropertyTagOrientation,您可以通过以下方式添加:

        using System.Runtime.Serialization;
        ..
    
        pi = (PropertyItem)FormatterServices
            .GetUninitializedObject(typeof(PropertyItem));
    
        pi.Id = 0x0112;   // orientation
        pi.Len = 2;
        pi.Type = 3;
        pi.Value = new byte[2] { 1, 0 };
    
        pi.Value[0] = yourOrientationByte;
    
        yourImage.SetPropertyItem(pi);
    

    向@ne1410s 的优秀answer here!致敬。

    注意在图片中添加PropertyItems不会添加exif数据;两者是不同的标签集!

    【讨论】:

    • 抱歉回答晚了,不得不找一些关于 EXIF 数据的文档。试了几张图,效果很好!非常感谢:)
    • 今天申请了。效果很好。只有两点:1)对于Rotate,我概括为Image,而不是更具体的Bitmap——有什么理由不这样做吗? 2) EXIF 旋转值的幻数 2-8 违反了我们的编码风格策略,所以我创建了一个枚举 just like here,因为它们在 .NET 框架库中没有定义/公开
    • 1) 那么Image 也可以是Icon 或WMF,但我希望两者都没有方向PropertyItem 所以我不想做出任何承诺;-)。 2)当然,有这样的政策很好;我通常尽量保持我的答案相当简单,没有枚举,没有检查等。顺便说一句:你会注意到RotateFlipType 枚举包含许多重复项;我已经选择了那些我最容易把头绕起来的东西..
    • 我将在此处提供哪些参数 - PropertyItem getPropertyItemByID(Image img, int Id)?我对 Id 部分感到困惑
    • 查看整个enumeration
    猜你喜欢
    • 2019-03-29
    • 2020-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多