C# 裁剪和调整大图像大小
Posted
技术标签:
【中文标题】C# 裁剪和调整大图像大小【英文标题】:C# Crop & resize large images 【发布时间】:2015-03-13 08:50:39 【问题描述】:我得到了一些非常大的建筑图纸,有时是 22466x3999,位深为 24,甚至更大。 我需要能够将这些调整为更小的版本,并且能够将图像的部分剪切成更小的图像。
我一直在使用以下代码来调整图像大小,我发现here:
public static void ResizeImage(string OriginalFile, string NewFile, int NewWidth, int MaxHeight, bool OnlyResizeIfWider)
System.Drawing.Image FullsizeImage = System.Drawing.Image.FromFile(OriginalFile);
if (OnlyResizeIfWider)
if (FullsizeImage.Width <= NewWidth)
NewWidth = FullsizeImage.Width;
int NewHeight = FullsizeImage.Height * NewWidth / FullsizeImage.Width;
if (NewHeight > MaxHeight)
NewWidth = FullsizeImage.Width * MaxHeight / FullsizeImage.Height;
NewHeight = MaxHeight;
System.Drawing.Image NewImage = FullsizeImage.GetThumbnailImage(NewWidth, NewHeight, null, IntPtr.Zero);
FullsizeImage.Dispose();
NewImage.Save(NewFile);
这个代码来裁剪图像:
public static MemoryStream CropToStream(string path, int x, int y, int width, int height)
if (string.IsNullOrWhiteSpace(path)) return null;
Rectangle fromRectangle = new Rectangle(x, y, width, height);
using (Image image = Image.FromFile(path, true))
Bitmap target = new Bitmap(fromRectangle.Width, fromRectangle.Height);
using (Graphics g = Graphics.FromImage(target))
Rectangle croppedImageDimentions = new Rectangle(0, 0, target.Width, target.Height);
g.DrawImage(image, croppedImageDimentions, fromRectangle, GraphicsUnit.Pixel);
MemoryStream stream = new MemoryStream();
target.Save(stream, image.RawFormat);
stream.Position = 0;
return stream;
我的问题是当我尝试调整图像大小时收到 Sytem.OutOfMemoryException,这是因为我无法将完整图像加载到 FullsizeImage。
那么我想知道的是,如何在不将整个图像加载到内存的情况下调整图像大小?
【问题讨论】:
这不是编程解决方案,但您可以尝试增加机器的虚拟内存大小并查看。 你应该使用 LockBits 来处理这样的图像尺寸 @Kurubaran 我尝试增加内存大小,但没有成功,我认为这不是 web 项目的正确解决方案。 【参考方案1】:OutOfMemoryException
有可能不是因为图像的大小,而是因为您没有正确处理所有一次性用品类:
Bitmap target
MemoryStream stream
System.Drawing.Image NewImage
没有按应有的方式处置。您应该在它们周围添加一个using()
声明。
如果您真的只使用一张图像遇到此错误,那么您应该考虑将您的项目切换到 x64。一张 22466x3999 的图片意味着 225Mb 的内存,我认为这对于 x86 来说应该不是问题。 (所以请先尝试处理您的对象)。
最后但同样重要的是,Magick.Net 在调整/裁剪大图片方面非常有效。
【讨论】:
谢谢,我会把using()
加到Fullsizeimage和其他地方。我确实尝试过 Magick.Net,但我无法让它工作,但如果这没有帮助,我会试一试。
Image Magick.Net 必须是要走的路,因为添加 using 仍然返回 OutOfMemoryException
。如果 Image Magick.Net 不起作用,我将创建一个单独的服务来处理所有图像大小调整和裁剪..
即使在大型 64 位系统上,您也无法创建任意大小的位图。如果他需要处理非常大的位图,恐怕使用 3rd 方库是最好的选择..
我觉得我需要对这个问题进行跟进,在添加了几个使用之后,它最终工作了。我认为您是对的,我多次使用该方法,并且在某些时候我会遇到异常。所以谢谢!另一个问题可能是它是一个 Web 应用程序,因此内存可能受到 IIS 内存上限的限制。【参考方案2】:
您还可以强制 .Net 直接从磁盘读取图像并停止内存缓存。
使用
sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);
代替
...System.Drawing.Image.FromFile(OriginalFile);
见https://***.com/a/47424918/887092
【讨论】:
以上是关于C# 裁剪和调整大图像大小的主要内容,如果未能解决你的问题,请参考以下文章
使用 Imagemagick 将大图像裁剪为特定的纵横比,然后调整它们的大小