我遇到了需要调整大量图像大小的情况。目前,这些图像以.jpg文件的形式存储在文件系统中,但我希望稍后在项目的内存中只有byte[]。源图像的大小是可变的,但输出应该是3个不同的预定大小。应该保留纵横比,用空白填充原始图像(即,真正高的图像将调整大小以适应正方形目标图像大小,左侧和右侧有大片白色区域)。
我最初构建该项目的目标是.NET 2.0,并使用System.Drawing类执行加载/调整大小/保存。相关代码包括:
original = Image.FromFile(inputFile); //NOTE: Reused for each of the 3 target sizes
Bitmap resized = new Bitmap(size, size);
//Draw the image to a new image of the intended size
Graphics g = Graphics.FromImage(resized);
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.Clear(Color.White);
g.DrawImage(original, center - width / 2f, center - height / 2f, width, height);
g.Dispose();
//Save the new image to the output path
resized.Save(outputFile, ImageFormat.Jpeg);我想将此项目移植到.NET 3.5,因此尝试使用System.Windows.Media类来执行相同的功能。我让它工作了,但是性能很糟糕;每个图像的处理时间大约增加了50倍。绝大多数时间都花在加载图像上。相关代码包括:
BitmapImage original = new BitmapImage(); //Again, reused for each of the 3 target sizes
original.BeginInit();
original.StreamSource = new MemoryStream(imageData); //imageData is a byte[] of the data loaded from a FileStream
original.CreateOptions = BitmapCreateOptions.None;
original.CacheOption = BitmapCacheOption.Default;
original.EndInit(); //Here's where the vast majority of the time is spent
original.Freeze();
// Target Rect for the resize operation
Rect rect = new Rect(center - width / 2d, center - height / 2d, width, height);
// Create a DrawingVisual/Context to render with
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext drawingContext = drawingVisual.RenderOpen())
{
drawingContext.DrawImage(original, rect);
}
// Use RenderTargetBitmap to resize the original image
RenderTargetBitmap resizedImage = new RenderTargetBitmap(
size, size, // Resized dimensions
96, 96, // Default DPI values
PixelFormats.Default); // Default pixel format
resizedImage.Render(drawingVisual);
// Encode the image using the original format and save the modified image
SaveImageData(resizedImage, outputFile);我是不是做错了什么,花了这么多时间?我已经尝试在BitmapImage上使用带有URI的构造函数,同样的性能问题也存在。有没有人以前做过类似的事情,知道有没有更注重性能的方法?或者我仍然需要使用System.Drawing?谢谢!
发布于 2009-11-17 07:17:02
在输入所有这些内容之后,我突然想到我可以从MS加载System.Windows.Media类的符号,并逐步执行速度较慢的部分。立即找到了原因,并找到了解决办法。输入图像与颜色配置文件一起保存,并尝试加载每个图像的颜色配置文件(从文件系统)。通过在上面的代码中从BitmapCreateOptions.None切换到BitmapCreateOptions.IgnoreColorProfile,它不再这样做,并且执行起来和System.Drawing一样快。
希望这篇文章能帮助任何遇到这个问题的人!
发布于 2009-11-17 13:34:35
你似乎是在以一种艰难的方式来做这件事。只需设置DecodePixelHeight和DecodePixelWidth,就可以让WPF为您完成这项工作。这将导致在映像加载期间进行大小调整:
BitmapImage resizedImage = new BitmapImage
{
StreamSource = new MemoryStream(imageData),
CreateOptions = BitmapCreateOptions.IgnoreColorProfile,
DecodePixelHeight = height,
DecodePixelWidth = width,
}
resizedImage.BeginInit(); // Needed only so we can call EndInit()
resizedImage.EndInit(); // This does the actual loading and resizing
imageSaveImageData(resizedImage, outputFile);我还包含了您在我的代码中找到的IgnoreColorProfile解决方案。
更新我重读了你的问题,我意识到你使用DrawingVisual的原因是你需要在你的图像周围留出空格来使它成为正方形。DecodePixelHeight和DecodePixelWidth无法实现该目标,因此我的解决方案没有回答您的问题。
我会在这里留下我的答案,以防那些只需要调整大小而不需要空格的人遇到这个问题。
发布于 2009-11-17 07:17:11
我认为MSDN上的System.Drawing页面上的这一点可能是相关的:
System.Drawing命名空间提供对GDI+基本图形功能的访问。System.Drawing.Drawing2D、System.Drawing.Imaging和System.Drawing.Text名称空间中提供了更高级的功能。Graphics类提供用于绘制到显示设备的方法。像Rectangle和Point这样的类封装了GDI+原语。Pen类用于绘制直线和曲线,而从抽象类Brush派生的类用于填充形状的内部。
与使用System.Windows.Media相比,使用System.Drawing更接近实际的基本图形功能:
定义的对象支持在Windows Presentation Foundation (WPF)应用程序中集成富媒体,包括绘图、文本和音频/视频内容。
System.Drawing仍然被支持,所以我会坚持使用它。
https://stackoverflow.com/questions/1745446
复制相似问题