简体   繁体   中英

Out of memory error while loading a Bitmap

I'm working with big size images (for ex. 16000x9440 px) and cut some regions for other things. I'm getting an exception "Out of memory" when create a new Bitmap instance:

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
                );
            }
        }
    }
}

When I use small image sizes (for ex. 8000x4720 px) then all work fine.

How can I work with big size images?

PS tile Bitmap is disposed in finally block.

Best regards, Alex.

You are using about a gigabyte of ram, not very suprising that you run out of memory.

Assuming you use a 32bpp Fileformat with 16000x9440 pixel you get a filesize of about:

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

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

You load the whole File into a memory stream, this requires 576MB.

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

You load the whole stream contents into a bitmap, this requires at least another 576MB (depending on how much memory the bitmap requires per pixel, should be at least 4, propably more). At that point you have the image twice in memory which seriously hurts for such big images.

You can reduce the memory footprint by getting rid of the memory stream and loading the bitmap directly from the file stream.

Another solution would be to load only a part of the bitmap and load the other parts on-demand (much like google maps), but i can't help you with that solution, might require reading the bitmap manually.

对你的问题不是一个完整的答案,但你最好使用像ImageMagick.NET这样的库

MemoryStream is implemented using an array of bytes that stores the data. If you read more data than the array can hold, a new array of double size is allocated and the bytes copied from one array to the other.

Since you apparently know how much data you're going to need, you can allocated the correct size up front and thus avoid the resizing.

However, once you reach a certain size you will run out of memory. .NET imposes a 2 GB limit on a single object ( even on 64 bit ), so the internal array in MemoryStream will never be able to grow beyond that. If your image is larger than that you'll get an out of memory exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM