C# 调整大小时,某些图像正在旋转

C# 调整大小时,某些图像正在旋转,c#,image,image-processing,image-rotation,C#,Image,Image Processing,Image Rotation,简而言之,下面代码的目的是根据目标大小和乘数(1x、2x、3x)调整图像大小。这工作正常,除了一些原因,我还没有确定一些图像正在旋转 public void ResizeImage(TargetSize TargetSize,ResizeMultiplier乘数,流输入,流输出) { 使用(var image=image.FromStream(输入)) { //计算调整大小因子 var scaleFactor=targetSize.CalculateScaleFactor(image.Width

简而言之,下面代码的目的是根据目标大小和乘数(1x、2x、3x)调整图像大小。这工作正常,除了一些原因,我还没有确定一些图像正在旋转

public void ResizeImage(TargetSize TargetSize,ResizeMultiplier乘数,流输入,流输出)
{
使用(var image=image.FromStream(输入))
{
//计算调整大小因子
var scaleFactor=targetSize.CalculateScaleFactor(image.Width,image.Height);
scaleFactor/=(int)乘数;//枚举有效地命名为常量,其值为1、2或3
var newWidth=(int)Math.Floor(image.Width/scaleFactor);
var newHeight=(int)Math.Floor(image.Height/scaleFactor);
使用(var newBitmap=新位图(newWidth、newHeight))
{
使用(var imageScaler=Graphics.FromImage(newBitmap))
{
imageScaler.CompositingQuality=CompositingQuality.HighQuality;
imageScaler.SmoothingMode=SmoothingMode.HighQuality;
imageScaler.InterpolationMode=InterpolationMode.HighQualityBicubic;
var imageRectangle=新矩形(0,0,newWidth,newHeight);
imageScaler.DrawImage(图像,图像矩形);
保存(输出,image.RawFormat);
}
}
}
}
//上述方法中使用的类的类定义
公共类目标大小
{
/// 
///宽度
/// 
私有只读整数宽度;
/// 
///高度
/// 
专用只读int_高度;
/// 
///初始化类的新实例。
/// 
///宽度。
///高度。
公共目标大小(整数宽度、整数高度)
{
_高度=高度;
_宽度=宽度;
}
/// 
///计算比例因子。
/// 
///宽度。
///高度。
/// 
公共十进制计算比例因子(整数宽度、整数高度)
{
//按比例缩放
var heightScaleFactor=十进制除法(高度,_高度);
var widthScaleFactor=decimal.Divide(宽度,_宽度);
//使用两者中较小的一个作为最终比例因子,这样图像就不会过小。
返回widthScaleFactor>heightScaleFactor?heightScaleFactor:widthScaleFactor;
}
}
//我用来练习上述代码的NUnit集成测试用例
[测试]
public void ResizeImage\u Persistant\u Single()
{
//从磁盘读取映像
使用(var fileStream=File.OpenRead(@“TestData\dog.jpg”))
{
使用(var outputStream=new MemoryStream())
{
//调用上面详述的ResizeImage方法。ResizeMultiplier.Medium强制转换为2。
_sut.ResizeImage(新TargetSize(200200)、ResizeMultiplier.Medium、fileStream、outputStream);
使用(var newImage=Image.FromStream(outputStream))
{
//将调整大小的图像保存到磁盘
newImage.Save(@“TestData\ImageResizerTests.ResizeImage_Persistant_Single.jpg”);
}
}
}
}
例如,此图像:

已适当缩放,但此图像:

被翻转过来。值得一提的是,在预览窗格中将图像上载到此站点时,图像似乎也颠倒了。这一事实(显然是我刚刚发现的)强烈地让我觉得这张照片很有趣。不管怎样,我的代码需要处理它

Imgur“修复”了上面的文件(因为在我运行代码时,它现在不会旋转),所以我将其上载到了。如果您右键单击图像(在FireFox中,我没有测试过其他浏览器),然后单击“将图像另存为…”。。。然后图像不会随着上面的代码旋转。如果您单击标题中的下载按钮,则图像将与我的代码一起旋转。。。。这是一个狗的形象,翻转180度与我的代码。所有这些都很奇怪,我不知道我做错了什么

为了清楚,我的目标是在不旋转图像的情况下调整图像大小


根据评论进行编辑:

旋转/翻转的图像将以相同的方式持续旋转/翻转。例如,此狗图片将始终翻转180度。有些图片将侧放(旋转90或270度)。我已经验证了当狗狗图片翻转180度时,
newWidth
newHeight
scaleFactor
targetSize
(私有变量)和
image.Height/image.Width
变量都是正值


我不相信这是特定工具的产物。我看到旋转通过;Windows资源管理器、Windows图像查看器、Macintosh股票图像查看器、FireFox等中的预览。实际上,我公司的一位iOS开发人员在我们的应用程序中看到了这个问题,引起了我的注意。我认为有太多的工具看到了这一点,这将成为一个查看器问题。

多亏了1和2的出色帮助,我才能够回答自己的问题

核心问题是一些图像上的EXIF数据改变了图像的方向。当我调整图像大小时,所有EXIF数据都被剥离。由于EXIF数据被剥离,观众不知道图像的方向应该不同。这让我觉得调整大小的代码正在旋转一些图像。值得注意的是,在Windows资源管理器中右键单击图像时,此方向信息不会显示在“详细信息”视图中。您需要在图像属性对象中搜索它,或使用类似的联机视图

使用3,我能够创建以下命名常量:

使用这些命名常量,我将我的
ResizeImage
方法扩展为:

public void ResizeImage(TargetSize targetSize, ResizeMultiplier multiplier, Stream input, Stream output)
{
    using (var image = Image.FromStream(input))
    {
        // Calculate the resize factor
        var scaleFactor = targetSize.CalculateScaleFactor(image.Width, image.Height);
        scaleFactor /= (int)multiplier; 

        var newWidth = (int)Math.Floor(image.Width / scaleFactor);
        var newHeight = (int)Math.Floor(image.Height / scaleFactor);
        using (var newBitmap = new Bitmap(newWidth, newHeight))
        {
            using (var imageScaler = Graphics.FromImage(newBitmap))
            {
                imageScaler.CompositingQuality = CompositingQuality.HighQuality;
                imageScaler.SmoothingMode = SmoothingMode.HighQuality;
                imageScaler.InterpolationMode = InterpolationMode.HighQualityBicubic;

                var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
                imageScaler.DrawImage(image, imageRectangle);

                // Fix orientation if needed.
                if (image.PropertyIdList.Contains(OrientationKey))
                {
                    var orientation = (int)image.GetPropertyItem(OrientationKey).Value[0];
                    switch (orientation)
                    {
                        case NotSpecified: // Assume it is good.
                        case NormalOrientation:
                            // No rotation required.
                            break;
                        case MirrorHorizontal:
                            newBitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
                            break;
                        case UpsideDown:
                            newBitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                            break;
                        case MirrorVertical:
                            newBitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
                            break;
                        case MirrorHorizontalAndRotateRight:
                            newBitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
                            break;
                        case RotateLeft:
                            newBitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                            break;
                        case MirorHorizontalAndRotateLeft:
                            newBitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
                            break;
                        case RotateRight:
                            newBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                            break;
                        default:
                            throw new NotImplementedException("An orientation of " + orientation + " isn't implemented.");
                    }
                }
                newBitmap.Save(output, image.RawFormat);
            }
        }
    }
}
有观察力的人会注意到,大多数附加代码都被拉到了一个相关的问题上


他说:谁在钱的问题上是对的,但我不明白他是什么
public void ResizeImage(TargetSize targetSize, ResizeMultiplier multiplier, Stream input, Stream output)
{
    using (var image = Image.FromStream(input))
    {
        // Calculate the resize factor
        var scaleFactor = targetSize.CalculateScaleFactor(image.Width, image.Height);
        scaleFactor /= (int)multiplier; 

        var newWidth = (int)Math.Floor(image.Width / scaleFactor);
        var newHeight = (int)Math.Floor(image.Height / scaleFactor);
        using (var newBitmap = new Bitmap(newWidth, newHeight))
        {
            using (var imageScaler = Graphics.FromImage(newBitmap))
            {
                imageScaler.CompositingQuality = CompositingQuality.HighQuality;
                imageScaler.SmoothingMode = SmoothingMode.HighQuality;
                imageScaler.InterpolationMode = InterpolationMode.HighQualityBicubic;

                var imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
                imageScaler.DrawImage(image, imageRectangle);

                // Fix orientation if needed.
                if (image.PropertyIdList.Contains(OrientationKey))
                {
                    var orientation = (int)image.GetPropertyItem(OrientationKey).Value[0];
                    switch (orientation)
                    {
                        case NotSpecified: // Assume it is good.
                        case NormalOrientation:
                            // No rotation required.
                            break;
                        case MirrorHorizontal:
                            newBitmap.RotateFlip(RotateFlipType.RotateNoneFlipX);
                            break;
                        case UpsideDown:
                            newBitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
                            break;
                        case MirrorVertical:
                            newBitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
                            break;
                        case MirrorHorizontalAndRotateRight:
                            newBitmap.RotateFlip(RotateFlipType.Rotate90FlipX);
                            break;
                        case RotateLeft:
                            newBitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);
                            break;
                        case MirorHorizontalAndRotateLeft:
                            newBitmap.RotateFlip(RotateFlipType.Rotate270FlipX);
                            break;
                        case RotateRight:
                            newBitmap.RotateFlip(RotateFlipType.Rotate270FlipNone);
                            break;
                        default:
                            throw new NotImplementedException("An orientation of " + orientation + " isn't implemented.");
                    }
                }
                newBitmap.Save(output, image.RawFormat);
            }
        }
    }
}