【发布时间】:2016-01-23 11:24:34
【问题描述】:
简而言之,以下代码的目的是根据目标大小和乘数(1x、2x、3x)调整图像大小。除了由于某种原因我还没有确定某些图像正在旋转之外,这很好用。
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; // Enum is effectively named constant with a value of 1, 2, or 3
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);
newBitmap.Save(output, image.RawFormat);
}
}
}
}
// Class definition for the class used in the method above
public class TargetSize
{
/// <summary>
/// The _width
/// </summary>
private readonly int _width;
/// <summary>
/// The _height
/// </summary>
private readonly int _height;
/// <summary>
/// Initializes a new instance of the <see cref="TargetSize"/> class.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
public TargetSize(int width, int height)
{
_height = height;
_width = width;
}
/// <summary>
/// Calculates the scale factor.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <returns></returns>
public decimal CalculateScaleFactor(int width, int height)
{
// Scale proportinately
var heightScaleFactor = decimal.Divide(height, _height);
var widthScaleFactor = decimal.Divide(width, _width);
// Use the smaller of the two as the final scale factor so the image is never undersized.
return widthScaleFactor > heightScaleFactor ? heightScaleFactor : widthScaleFactor;
}
}
// NUnit integration test case I'm using to exercise the above code
[Test]
public void ResizeImage_Persistant_Single()
{
// Read the image from disk
using (var fileStream = File.OpenRead(@"TestData\dog.jpg"))
{
using (var outputStream = new MemoryStream())
{
// Call the resize image method detailed above. ResizeMultiplier.Medium casts to 2.
_sut.ResizeImage(new TargetSize(200, 200), ResizeMultiplier.Medium, fileStream, outputStream);
using (var newImage = Image.FromStream(outputStream))
{
// Save the resized image to disk
newImage.Save(@"TestData\ImageResizerTests.ResizeImage_Persistant_Single.jpg");
}
}
}
}
例如这张图片:
已适当缩放,但此图像:
被颠倒过来。值得一提的是,当它在预览窗格中上传到该站点时,图像也出现了颠倒。这个事实(我显然刚刚发现)强烈地让我觉得这张照片很有趣。不管我的代码需要处理它。
Imgur“修复”了上面的文件(因为当我通过我的代码运行它时它现在不会旋转)所以我将它上传到Google Drive。如果您右键单击图像(在 FireFox 中我没有测试过其他浏览器)并单击 Save Image As... 那么图像不会随着我上面的代码旋转。如果您单击标题中的下载按钮,则图像会随我的代码旋转.... 这是狗图像的another copy,它使用我的代码翻转 180 度。这一切都很离奇,不知道自己做错了什么……
要明确我的目标是在不旋转图像的情况下调整图像大小。
基于 cmets 的编辑:
旋转/翻转的图像会以相同的方式始终如一地进行。例如,这张狗图片将始终翻转 180 度。有些图片会侧放(旋转 90 或 270 度)。我已经验证了当狗图片翻转 180 度时,newWidth、newHeight、scaleFactor、targetSize(私有变量)和image.Height/image.Width 变量都是正数。
我不相信这是特定工具的产物。我看到了旋转; Windows Explorer、Windows Image Viewer、库存 Macintosh 图像查看器、FireFox 等中的预览。这个问题实际上是由我公司的一位 iOS 开发人员在我们的应用程序中看到的。我认为有太多工具看到了这一点,而不是查看器问题。
【问题讨论】:
-
这可能是一个愚蠢的问题,但你确定这不是你用来查看图像的任何工具的产物吗?一些图像查看器可能会尝试通过将面部定向为直立和/或使用其他图像提示来“纠正”方向来帮助您。
-
相机 EXIF 信息有时可用于自动旋转图像,但我从未见过它会颠倒某些东西。
-
根据我在regex.info/exif.cgi 找到的第一个在线EXIF 查看器,这只狗确实旋转了180 度(
Orientation字段)。
标签: c# image image-processing image-rotation