.Net 缩略图在从移动设备创建时旋转图像

标签 .net vb.net bitmap resize exif

我正在使用旧问题的以下答案中的代码来设置上传图片的缩略图。

https://stackoverflow.com/a/2001462/1593395

这非常有效,可以填充图像,保持纵横比等,但是如果我从手机上传图像,通过这种方法保存的缩略图会逆时针旋转 90 度。

你知道是什么原因造成的吗?原始图像仅使用 AjaxFileUpload1.SaveAs(MapPath("~/catalog/images/"& imageFilename))(来自 AJAX 控制工具包)保存,并以正确的方向显示。

谢谢

最佳答案

可能是由于图像的物理存储方向与其显示方向不同,例如,用相机侧面拍摄的 640*480 镜头可能会存储为 480*640,并带有方向 exif 数据标志。

这很棒,因为 explorer/paint/photoshop/几乎每个查看者都会看到 exif 标志并在渲染之前旋转它。但是,.net Image 类没有(当你知道发生了什么时这似乎是合理的),所以你必须在新的缩略图上设置 exif 旋转属性(我不想这样做,只是因为我不喜欢在缩略图上有任何属性)或自己检查和旋转缩略图。

下面是一个粗略的方法来做到这一点。请注意,我已经在 c# 中提供了代码作为您引用的答案的修改版本,因为它也是 c#。转换到 vb.net 应该非常简单:)

  if (sourceImage.PropertyIdList.Contains(0x112)) //0x112 = Orientation
  {
     var prop = sourceImage.GetPropertyItem(0x112);
     if (prop.Type == 3 && prop.Len == 2)
     {
        UInt16 orientationExif = BitConverter.ToUInt16(sourceImage.GetPropertyItem(0x112).Value, 0);
        if (orientationExif == 8)
        {
           newImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
        }
        else if (orientationExif == 3)
        {
           newImage.RotateFlip(RotateFlipType.Rotate180FlipNone);
        }
        else if (orientationExif == 6)
        {
           newImage.RotateFlip(RotateFlipType.Rotate90FlipNone);
        }
     }
  }

因此更新后的 FixedSize 代码将是这样的:

static Image FixedSize(Image imgPhoto, int Width, int Height)
{
    int sourceWidth = imgPhoto.Width;
    int sourceHeight = imgPhoto.Height;
    int sourceX = 0;
    int sourceY = 0;
    int destX = 0;
    int destY = 0;

    float nPercent = 0;
    float nPercentW = 0;
    float nPercentH = 0;

    nPercentW = ((float)Width / (float)sourceWidth);
    nPercentH = ((float)Height / (float)sourceHeight);
    if (nPercentH < nPercentW)
    {
        nPercent = nPercentH;
        destX = System.Convert.ToInt16((Width -
                      (sourceWidth * nPercent)) / 2);
    }
    else
    {
        nPercent = nPercentW;
        destY = System.Convert.ToInt16((Height -
                      (sourceHeight * nPercent)) / 2);
    }

    int destWidth = (int)(sourceWidth * nPercent);
    int destHeight = (int)(sourceHeight * nPercent);

    Bitmap bmPhoto = new Bitmap(Width, Height,
                      PixelFormat.Format24bppRgb);
    bmPhoto.SetResolution(imgPhoto.HorizontalResolution,
                     imgPhoto.VerticalResolution);

    Graphics grPhoto = Graphics.FromImage(bmPhoto);
    grPhoto.Clear(Color.Red);
    grPhoto.InterpolationMode =
            InterpolationMode.HighQualityBicubic;

    grPhoto.DrawImage(imgPhoto,
        new Rectangle(destX, destY, destWidth, destHeight),
        new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight),
        GraphicsUnit.Pixel);

    grPhoto.Dispose();

    //Rotate image to what is expected.
    if (imgPhoto.PropertyIdList.Contains(0x112)) //0x112 = Orientation
    {
       var prop = imgPhoto.GetPropertyItem(0x112);
       if (prop.Type == 3 && prop.Len == 2)
       {
          UInt16 orientationExif = BitConverter.ToUInt16(sourceImage.GetPropertyItem(0x112).Value, 0);
          if (orientationExif == 8)
          {
             bmPhoto.RotateFlip(RotateFlipType.Rotate270FlipNone);
          }
          else if (orientationExif == 3)
          {
             bmPhoto.RotateFlip(RotateFlipType.Rotate180FlipNone);
          }
          else if (orientationExif == 6)
          {
             bmPhoto.RotateFlip(RotateFlipType.Rotate90FlipNone);
          }
       }
    }

    return bmPhoto;
}

请注意,这并不涵盖所有 exif 方向,仅涵盖常见方向。

引用资料:

http://www.impulseadventure.com/photo/exif-orientation.html

http://msdn.microsoft.com/en-us/library/xddt0dz7.aspx

p.s:那是我的第一个堆栈溢出答案,所以请在反馈上放轻松 ;)

关于.Net 缩略图在从移动设备创建时旋转图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19591216/

相关文章:

c# - 如何比较两个富文本框内容并高亮显示变化的字符?

asp.net - 设置 asp :TextBox 的日期格式

c# - 使用 EWS 托管 API 将 .msg 文件上传到 Exchange Server

android - 从指定的屏幕区域创建位图

actionscript-3 - Flash CC 不会嵌入图像资源

c# - 如何让 Swagger 显示从 API 返回的对象示例?

c# - .Net 枚举 winforms 字体样式?

.net - MsgBox 出现在 VB.NET 的启动画面下方

.net - 将所选行从 DataGridView 复制到另一个,包括图像列

java - 如何在 Android 上高效存储位集