c# - 加载位图时出现内存不足错误

标签 c# .net exception bitmap out-of-memory

我正在处理大尺寸图像(例如 16000x9440 像素)并为其他内容剪切一些区域。创建新的位图实例时出现“内存不足”异常:

using (FileStream fileStream = new FileStream(mapFileResized, FileMode.Open))
{
    byte[] data = new byte[fileStream.Length];
    fileStream.Read(data, 0, data.Length);
    using (MemoryStream memoryStream = new MemoryStream(data))
    {
        using (Bitmap src = new Bitmap(memoryStream)) // <-- exception
        {
            tile = new Bitmap(tileWidth, tileHeight, PixelFormat.Format24bppRgb);
            tile.SetResolution(src.HorizontalResolution, src.VerticalResolution);
            tile.MakeTransparent();
            using (Graphics grRect = Graphics.FromImage(tile))
            {
                grRect.CompositingQuality = CompositingQuality.HighQuality;
                grRect.SmoothingMode = SmoothingMode.HighQuality;
                grRect.DrawImage(
                        src,
                        new RectangleF(0, 0, tileWidth, tileHeight),
                        rTile,
                        GraphicsUnit.Pixel
                );
            }
        }
    }
}

当我使用小图像尺寸(例如 8000x4720 像素)时,一切正常。

如何处理大尺寸图像?

PS tile Bitmap 在 finally block 中处理。

最好的问候,亚历克斯。

最佳答案

您正在使用大约 1 GB 的内存,内存不足并不奇怪。

假设您使用具有 16000x9440 像素的 32bpp 文件格式,您得到的文件大小约为:

16000 * 9440 * (32/8) = ~576MB

byte[] data = new byte[fileStream.Length];
fileStream.Read(data, 0, data.Length);
using (MemoryStream memoryStream = new MemoryStream(data))
{
  [... snip ...]
}

您将整个文件加载到内存流中,这需要 576MB。

[... snip ...]
    using (Bitmap src = new Bitmap(memoryStream)) // <-- exception
    {
        [... snip ...]
    }
[... snip ...]

您将整个流内容加载到位图中,这至少需要另外 576MB(取决于位图每个像素需要多少内存,应该至少为 4,可能更多)。那时你的图像在内存中有两次,这对这么大的图像造成了严重的伤害。

您可以通过摆脱内存流并直接从文件流加载位图来减少内存占用。

另一种解决方案是仅加载位图的一部分并按需加载其他部分(很像谷歌地图),但我无法帮助您解决该解决方案,可能需要手动读取位图。

关于c# - 加载位图时出现内存不足错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3117402/

相关文章:

.net - 使用 kSoap 将 ArrayList 从 .net web 服务返回到 android 应用程序

Python:在 __init__ 中引发异常是不好的形式吗?

delphi - Delphi中如何引发异常?

c# - c# for dns less 中 ms access 数据库 2010 的连接字符串

c# - 在 ASP.NET Core 2.x 中实现 EasyNetQ 发布/订阅模式的正确方法是什么?

javascript - 如何在 Javascript 函数中迭代 @Model.ICollection?

c# - .NET 5 如何构建 netcoreapp3.1?

错误代码处理程序抛出的异常的 Javadoc @throws 标记

C# 如何从字符串中获取单词

c# - asp.net c#如何处理null?