Как создать bitmap большого размера в C#?

Пытаюсь создать битмап 30к на 30к, но вылетает ArgumentException.

var bitmap = new Bitmap(30000, 30000);

Проблема решила библиотека ImageSharp, но с ней у меня изображения не подгружаются полностью и есть артефакты. Как создать битмап большого размера без доп. библиотек и массива битмапов (одно из решений, что я нашел на SO) ? Если есть способ создать полотно большого размера для размещения картинок на нём, то готов рассмотреть другой способ.

Что я пробовал: прописывал gcallowverylargeobjects = true Приложение: Консоль, .NET 6 (пробовал и .NET 5) Компьютер мощный, ОЗУ должно хватать точно (64гб)


Ответы (1 шт):

Автор решения: aepot

Максимальный Bitmap, который вы можете создать с помощью GDI+ может весить максимум int.MaxValue байт. Это ограничение на уровне библиотеки GDI+ и обойти его невозможно, если вы конечно хотите продолжать использовать System.Drawing.

То есть если глубина цвета 32bpp, то размер при ширине 30000

2147483647 / 4 / 30000 = 17895

То есть код

Bitmap bitmap = new Bitmap(30000, 17895, PixelFormat.Format32bppArgb);

Сработает, но можно еще если вам не нужна прозрачность сделать 3 байта на пиксель 24bpp

2147483647 / 3 / 30000 = 23860

Получится так

Bitmap bitmap = new Bitmap(30000, 23860, PixelFormat.Format24bppRgb);

То есть, чтобы покрыть площадь 30000x30000 для полноцветного изображения, вам потребуется как минимум 2 битмапа.

Но если вам цветов надо немного, можно создать 8-битный битмар (1 байт на пиксель) и залить в него свою палитру, если требуется, тогда

2147483647 / 30000 = 71582

То есть код

Bitmap bitmap = new Bitmap(30000, 30000, PixelFormat.Format8bppIndexed);

Сработает без проблем.

Я бы конечно посоветовал область изображения разделить на тайлы, например 10000x10000 пикселей и использовал бы 9 тайлов. Чем меньше битмап - тем быстрее с ним работать.


Кстати, немного арифметики

Console.WriteLine(unchecked(30000 * 30000 * 4)); // -694967296

То есть из-за переполнения int значения, GDI+ получает отрицательное число при расчете размера изображения, отсюда и возникает ArgumentException.

→ Ссылка