当处理非常大的图像时,如何避免位图内存不足:即10.000.000像素及以上

目前我正在开发一个加载非常大的图像的系统,最小宽度x高度= = 10.000.000像素。

但是用户上传图像的比例通常与我们的要求比率不匹配,所以我必须将其裁剪为适当的比例,但是当使用System.Drawing位图裁剪它时,我总是得到SytemOutOfMemoryexception。

我尝试使用正确的RectangleF但没有运气的Bitmap.Clone和Graphic.DrawImage。

反正有没有得到outofmemoryexception,或者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); } 

而CropImagefunction:

 //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  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[])); } } 

您可以将位图转换为字节数组。 尝试这样的事情(看起来像hackie但我不知道另一种方式):

 int pixelSize = 3; int bytesCount = imgHeight * imgWidth * pixelSize; byte[] byteArray= new byte[bytesCount]; BitmapData bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, imgWidth, imgHeight), ImageLockMode.ReadOnly, bitmap.PixelFormat); Marshal.Copy(bitmapData.Scan0, byteArray, 0, bytesCount); 

此数组中的每个像素由3个字节表示(这取决于位图类型)。 所以你知道位图线的长度是3 * imgWidth。 使用它,您可以简单地在字节数组中导航,并将您需要的内容复制到新数组中。

然后,您将创建一个具有所需最终大小的新位图,获取位图数据和Marshal。将新数组复制到:

 Bitmap newBitmap = new Bitmap(Width, Height); BitmapData newBitmapData = b.LockBits(BoundsRect, ImageLockMode.WriteOnly, newBitmap.PixelFormat); Marshal.Copy(newByteArray, 0, newBitmapData.Scan0, newBytesCount); 

最后解锁位图:

 newBitmap.UnlockBits(newBitmapData ); bitmap.UnlockBits(bitmapData); 

希望这可以帮助。 干杯。

尝试使用graphicsmagick.net库,然后在MagickImage上使用Crop方法。 它应该仍然可以在asp.net下运行,并使用磁盘处理大量图像文件。