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