c#-使用.Clone()裁剪位图时内存不足教程
我正在尝试根据用户上传的图像自动生成缩略图,但始终收到“内存不足”的异常.
据我了解,当您指定图像以外的开始位置或宽度/高度时,会抛出内存不足异常,即使我这样做
var rct = new Rectangle(5, 5, 10, 10);
var whatever = bitmap.Clone(rct, bitmap.PixelFormat);
在800×900像素的图像上,我仍然会收到“内存不足”异常,我无法弄清楚问题出在哪里,并且由于与OOM异常有关的所有内容,我也无法真正从其他线程中获得任何好的答案.超出图像边界的错误.
有人对此有解释或解决方案吗?
编辑:更多上下文
图像循环.
foreach (var blob in fileInfoList)
{
var blockBlobName = CheckExistence(BaseBlobUrl, blob.FileName, blob.FileNameWithoutExtension);
var image = new Image()
{
BlobUrl = Path.Combine(BaseBlobUrl, blockBlobName),
FullName = blob.FileName,
FileName = blob.FileNameWithoutExtension,
BlockBlobName = blockBlobName,
OwningOrganizationId = CurrentUser.UserOrganization.OrganizationId,
ThumbnailUrl = CreateThumbnail(blob.File, blockBlobName),
Name = "Whatever"
};
blobList.Add(image);
RepositoryFactory.AzureStorageRepository.SaveImage(blob.File, blockBlobName, blob.ContentType, CurrentUser.UserOrganization.Organization.Id);
}
列表中每个图像所调用的生成缩略图的方法.
public string CreateThumbnail(byte[] b, string parentImageName)
{
Bitmap bmp;
using (var ms = new MemoryStream(b))
{
bmp = new Bitmap(ms);
}
Bitmap thumbnail = bmp;
Rectangle rect = new Rectangle(5, 5, 10, 10);
if (bmp.Width > bmp.Height)
thumbnail = bmp.Clone(rect, bmp.PixelFormat);
else if (bmp.Height > bmp.Width)
thumbnail = bmp.Clone(new Rectangle((bmp.Height/2) - (bmp.Width/2), 0, bmp.Width, bmp.Width), bmp.PixelFormat);
byte[] bmpArray = new byte[0];
using (var ms = new MemoryStream())
{
finalCrop.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Close();
bmpArray = ms.ToArray();
}
var name = "Thumbnail_" + parentImageName;
RepositoryFactory.AzureStorageRepository.SaveThumbnail(bmpArray, name, "jpg/image", CurrentUser.UserOrganization.Organization.Id);
return BaseBlobUrl + "thumbnails/" + name;
}
解决方法:
我认为您遇到的问题是需要处理位图.如果在不释放其底层非托管内容(即被处置)的情况下收集了垃圾,那么该内存将无法恢复…
还要注意,您将需要同时放置两个位图.最好的办法是将它们包装在using中,如下所示:
using (var ms = new MemoryStream(b))
{
using (Bitmap bmp = new Bitmap(ms))
using (Bitmap thumbnail = bmp)
{
Rectangle rect = new Rectangle(5, 5, 10, 10);
if (bmp.Width > bmp.Height)
thumbnail = bmp.Clone(rect, bmp.PixelFormat);
else if (bmp.Height > bmp.Width)
thumbnail = bmp.Clone(new Rectangle((bmp.Height / 2) - (bmp.Width / 2), 0, bmp.Width, bmp.Width), bmp.PixelFormat);
byte[] bmpArray = new byte[0];
using (var ms = new MemoryStream())
{
finalCrop.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
ms.Close();
bmpArray = ms.ToArray();
}
var name = "Thumbnail_" + parentImageName;
RepositoryFactory.AzureStorageRepository.SaveThumbnail(bmpArray, name, "jpg/image", CurrentUser.UserOrganization.Organization.Id);
return BaseBlobUrl + "thumbnails/" + name;
}
}
值得注意的是,即使抛出异常,使用也会在目标上调用Dispose()(因此,最终类型功能与@Scott Chamberlain答案相同)