【发布时间】:2015-06-15 05:08:48
【问题描述】:
目前我正在开发一个加载非常大图像的系统,最小宽度 x 高度 >= 10.000.000 像素。
但是用户上传图片的比例通常不符合我们要求的比例,所以我必须将它裁剪到适当的比例,但是当使用 System.Drawing 位图进行裁剪时,我总是遇到 SytemOutOfMemory 异常。
我用正确的 RectangleF 尝试了 Bitmap.Clone 和 Graphic.DrawImage,但没有运气。
是否有办法在不出现内存不足异常的情况下执行此操作,或者是否有任何替代 System.Drawing 库的方法可以轻松完成此任务?
我从用户上传文件加载图像的代码:
var fileBinary = new byte[stream.Length];
stream.Read(fileBinary, 0, fileBinary.Length);
stream.Position = 0;
var fileExtension = Path.GetExtension(fileName);
using (Image image = Image.FromStream(stream, false, false))
{
//validation and check ratio
CropImage(image, PORTRAIT_RATIO, fileExtension);
}
还有 CropImage 函数:
//Crop Image from center with predefine ratio
private byte[] CropImage(Image sourceImg, float ratio, string fileExtension)
var height = sourceImg.Height;
var width = sourceImg.Width;
var isPortrait = width < height;
RectangleF croppingRec = new RectangleF();
float positionX = 0;
float positionY = 0;
float cropHeight = (float)height;
float cropWidth = cropHeight * PORTRAIT_RATIO;
positionY = 0;
positionX = (width - cropWidth) / 2;
if (cropWidth > width)
{
cropWidth = width;
cropHeight = cropWidth * (1 / PORTRAIT_RATIO);
positionX = 0;
positionY = ((height - cropHeight) / 2);
}
croppingRec.Width = cropWidth;
croppingRec.Height = cropHeight;
croppingRec.X = positionX;
croppingRec.Y = positionY;
Bitmap bmpImage = sourceImg as Bitmap;
Bitmap bmpCrop = bmpImage.Clone(croppingRec, bmpImage.PixelFormat);
bmpCrop.Save("D:/test" + fileExtension, ImageFormat.Jpeg);
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(bmpCrop, typeof(byte[]));
}
}
【问题讨论】:
-
您是否尝试编译为带有特殊标志的
64bit应用程序,该标志消除了 clr 的内存限制(单个 List集合的最大 2GB 除外)? -
1000 万像素通常不是问题,十亿是理论上的最大值,但在 32 位进程中,您往往会在此之前跌倒。如果您的程序已经运行了一段时间,通常约为 2500 万。您的代码中最有可能出现的错误是忘记调用 Dispose(),当您使用 Bitmap 类时,这是一个非常严格的要求,并且太多的程序员忘记了它。如果您不发布代码,任何人都无法看到您的错误。
-
既然您提到了上传,可能值得您注意System.Drawing namespace 上的警告:“不支持在 Windows 或 ASP 中使用 System.Drawing 命名空间中的类.NET 服务。”
-
从代码中可以明显看出,bmpCrop 永远不会被释放。转换为 byte[] 后必须这样做。
-
究竟在哪里抛出异常?
标签: c# bitmap system.drawing