How to create a Bitmap larger than 9999 pixels

Asked

Viewed 121 times

3

When trying a create a Bitmap I realized I can’t create with the size I wanted, I need an image with 16581375 x 1.

Bitmap image = new Bitmap(16581375, 1);
image.Save("Path aqui");

When I try to execute this code it returns me the error:

System.Runtime.Interopservices.Externalexception: 'Generic GDI error+.'

1 answer

1

According to this reply from Soen this is a GDI+ limitation imposed by Windows.

"GDI" creates a memory-mapped file view for bitmap pixel data. This makes it very efficient, bitmaps tend to be large and MMF helps keep pixel data out of the paging file. RAM pages can simply be dropped and re-read from the file.

Windows restricts the size of the view in an MMF, i.e., the amount of data in the file that can be directly directed, as documented in this MSDN article:

The size of a file mapping object that is supported by a named file is limited by disk space. The size of a file view is limited to the largest available contiguous block of non-reserved virtual memory. This is at most 2GB or less than virtual memory already reserved by the process.

"The largest continuous block available" is the restriction in a 32-bit process, tends to rotate around ~600MB, give or take. The 2GB limit enters a 64 bit process.

Technically, "GDI" can ignore this limit when rewriting the view. But no, the method LockBits() (also widely used internally) would be inefficient and very strange to use.

To use larger bit maps, you can use the GDI+ successor which is the WIC (Windows Imaging Component).

Available in . NET via namespace System.Windows.Media.Imaging.


Memory limit

The size limit is due to the virtual memory limit, it has nothing to do with the amount of memory you have on your machine, remember other programs and even windows server (or your local windows) already use a lot of memory, which may be limiting, see an example of how to know how much memory has available:

using System;
using System.Diagnostics;

public class MemoryAvaliable
{
    static void Main(string[] args)
    {

        //Em Bytes
        using (PerformanceCounter perfCounter = new PerformanceCounter("Memory", "Available Bytes"))
        {
            long availableMemory = Convert.ToInt64(perfCounter.NextValue());
            Console.WriteLine(availableMemory);
        }

        //Em MB
        using (PerformanceCounter perfCounter = new PerformanceCounter("Memory", "Available MBytes"))
        {
            long availableMemory = Convert.ToInt64(perfCounter.NextValue());
            Console.WriteLine(availableMemory);
        }
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.