目前我正在开发一个加载非常大的图像的系统,最小宽度x高度> = 10.000.000像素。
但是用户上传图片的比例通常与我们的要求比率不匹配,所以我必须将其裁剪为适当的比例,但是当使用System.Drawing位图裁剪它时,我总是得到SytemOutOfMemory异常。
我尝试使用正确的RectangleF但没有运气的Bitmap.Clone和Graphic.DrawImage。
在没有获得outofmemory异常的情况下是否仍然可以执行此操作,或者是否有任何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[]));
}
}
答案 0 :(得分:2)
您可以将位图转换为字节数组。尝试这样的事情(看起来像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);
希望这会有所帮助。欢呼声。