c# – How to Create a Bitmap Larger Than 9999 Pixels

Question:

When trying to create a Bitmap I realized that 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 run this code it returns the error:

System.Runtime.InteropServices.ExternalException: 'GDI+ generic error.'

Answer:

As per this SOen answer this is a GDI+ limitation imposed by Windows.

"GDI" creates a memory-mapped file preview for the 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 discarded and re-read from the file.

Windows restricts the display size in an MMF, that is, the amount of data in the file that can be targeted directly, 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 contiguous available block of unreserved virtual memory. This is a maximum of 2GB or less of virtual memory already reserved by the process.

"Largest continuous block available" is the restriction on a 32-bit process, tends to be around ~600MB give or take. The 2GB limit goes into a 64-bit process.

Technically, "GDI" can bypass this limit when rescaling the display. But no, the LockBits() method (also used a lot internally) would be inefficient and very awkward to use.

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

Available in .NET through the System.Windows.Media.Imaging namespace.


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 the windows server (or your local windows) already use a good part of the memory, the which may be limiting, see an example of how to know how much memory you have 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);
        }
    }
}
Scroll to Top