【发布时间】:2025-12-10 13:10:01
【问题描述】:
在我的应用程序中,我正在处理大约 30 - 70 张大图像。工作是指加载、裁剪、调整大小和添加到 aviStream。每个图像最多可以有 4500p 和 10MB(处理如此大的图像会给我带来大部分内存不足的异常)。在测试时,我有时会使用较小的(每个 2500p ~ 500kB)并且内存情况要好得多。
我已将程序的架构更改为:加载一张图像,处理所需的操作,将其添加到流中,然后关闭它。并对下一张图片做同样的事情。但由于代码的复杂性和大小,我不能 100% 确定在此过程中我会处理并关闭为临时目的创建的每个位图和图像。
我有以下错误:
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
通常在裁剪图像时:
public static Image Crop(Image imgPhoto, Point xy, int width, int height) {
Rectangle cropRect = new Rectangle(xy, new Size(width, height));
Bitmap target = new Bitmap(cropRect.Width, cropRect.Height);
using (Graphics g = Graphics.FromImage(target)) {
g.DrawImage(imgPhoto, new Rectangle(0, 0, target.Width, target.Height), cropRect, GraphicsUnit.Pixel);
}
return target;
}
根据裁剪级别抛出异常,如果我裁剪大图像的一小部分,假设中间为 800x600 像素,那就更好了。如果以相反的方式裁剪,可以说创建一个 3500x2500 的图像,其中原始图像较小(空白区域将自动填充所选颜色),我大部分时间都有例外。
还有一个有趣的事情是,在第 23 张图像附近抛出异常,所以之前的图像处理得很好。
你们能给我一个如何调试的建议吗?我曾尝试扫描代码以查找未处理的图像和位图,但似乎没有找到所有这些。
因此,最大的问题是:如何一张一张地处理所有图像而不会出现异常?
【问题讨论】:
-
我会说这是一个 Dispose 问题,但如何轻松找到它们……那是另一回事。
-
好吧,
Bitmap没有被释放,它是从函数返回的。我假设调用代码也不会处理它。此外,如果您正在处理许多大图像,也许可以尝试重用缓冲区,而不是重新分配它。 -
我正在部分重用它们,但我也有很多这些方法,我在一些更改后返回原始输入图像。如果我是正确的,在这种情况下只有一个图像,并且只发送一个参考。所以我不能处理它,否则我会丢失我的原始数据,对吧?
-
在此函数中,您不会返回原始图像,而是返回一个新图像 (
new Bitmap(cropRect.Width, cropRect.Height)),其中一些数据是从原始图像复制而来的。我不可能用这些很少的信息告诉你如何有效地做到这一点。 “返回”图像但避免分配图像的一种方法是在调用代码中分配“目标”,然后将其作为参数发送给所有编辑函数。 -
非常感谢 TaW。没有尝试过,因为我认为它会删除目标的“占位符”,它将返回到其中。我不得不说,经过几次测试,它现在可以正常工作了。没有例外,并且在操作过程中 RAM 不会增加。这似乎解决了我的问题,所以再次感谢 TaW。
标签: c# image graphics out-of-memory drawimage