Я хотел бы иметь возможность создавать большое (скажем, 20 000 x 20 000) растровое изображение пикселей в приложении C++ MFC, используя производный класс CDC для записи в растровое изображение. Я пробовал использовать контроллеры домена памяти, как описано в документации MSDN, но они, похоже, ограничены размерами, совместимыми с текущим драйвером дисплея.
В настоящее время я использую драйвер печати растрового изображения для выполнения этой работы, но он работает очень медленно и использует очень большие объемы промежуточного хранилища из-за буферизации информации GDI.
Решение, которое я ищу, не должно включать метафайлы или буферизацию, поскольку модель, которую я рисую, требует для рендеринга многих миллионов вызовов GDI.
Я мог бы использовать подход «разделяй и властвуй» с помощью нескольких контроллеров домена памяти, но это кажется довольно громоздким и неэлегантным методом.
Какие-нибудь мысли?





Это необычно, поскольку я часто создавал DC на основе экрана, который будет использоваться для растрового изображения, которое намного больше, чем экран - 3000 пикселей плюс в некоторых случаях - без каких-либо проблем. У вас есть образец кода, показывающий эту проблему в действии?
CDC и CBitmap, похоже, поддерживают только растровые изображения, зависящие от устройства, возможно, вам больше повезет, если вы создадите свое растровое изображение с помощью :: CreateDIBSection, а затем прикрепите к нему CBitmap. К сожалению, необработанные интерфейсы GDI выглядят немного устаревшими.
Вам, вероятно, не повезет с 20000 x 20000 при 32 битах на пиксель, по крайней мере, в 32-битном приложении, поскольку это занимает около 1,5 ГБ памяти, но я получил действительный HBITMAP с 16 битами на пиксель:
BITMAPINFOHEADER bmi = { sizeof(bmi) };
bmi.biWidth = 20000;
bmi.biHeight = 20000;
bmi.biPlanes = 1;
bmi.biBitCount = 16;
HDC hdc = CreateCompatibleDC(NULL);
BYTE* pbData = 0;
HBITMAP hbm = CreateDIBSection(hdc, (BITMAPINFO*)&bmi, DIB_RGB_COLORS, (void**)&pbData, NULL, 0);
DeleteObject(SelectObject(hdc, hbm));
Учитывая такое большое разрешение изображения, вы не можете создать изображение, используя совместимые растровые изображения.
Пример:
глубина пикселя = 32 бита = 4 байта на пиксель
количество пикселей = 20,000 * 20,000 = 400,000,000
общее количество байтов = количество пикселей * 4 = 1.600.000.000 байтов = 1.562.500 кб ~ = 1525 МБ ~ = 1.5 ГБ
Я размышляю о конечных намерениях, но предположим, что вы хотите создать и позволить пользователям исследовать огромную карту с очень подробным увеличением. Вы должны создать собственный формат файла изображения; вы можете поместить в этот файл различные слои, содержащие сетки растровых изображений, например, для ускорения рендеринга. Процесс рендеринга может использовать GDI DIB или GDI + для создания частичных изображений, а затем их рендеринга вместе. Конечно, это требует некоторого экспериментирования / оптимизации, чтобы достичь идеального пользовательского ощущения.
удачи
xoreax, совершенно верно насчет размера и точного отображения в приложении для картографии. Глубина цвета - это 8 битов, которые составляют немного меньше 400 МБ для необработанного растрового изображения, что намного меньше, чем для JPEG. Саймон, ваш ответ CreateDIB на данный момент сработал. Я проверю SVG позже.
Если изображение должно иметь такое разрешение - скажем, сканирование рентгеновского снимка в высоком разрешении - тогда вы можете попробовать написать для него специальные процедуры буферизации - 1,5 ГБ очень дорого - даже для современных настольных компьютеров.
Если он основан на векторе, вы можете посмотреть на SVG, поскольку он поддерживает порты просмотра и большинство из них позволяет выполнять рендеринг в других форматах. Я использую SVG в JPG через Batik (java), так что это возможно.
Чтобы использовать память в допустимых пределах, вам придется использовать стратегию «разделяй и властвуй». Это не взлом, если все реализовано правильно, на самом деле это очень элегантный способ работы с растровыми изображениями неограниченного размера. Если вы спроектируете его правильно, вы можете объединить подходы «визуализировать / отображать только часть изображения», «визуализировать все изображение с низким разрешением для отображения на экране» и «визуализировать все это в растровое изображение на диске» в один движок и защитите пользователей вашего кода (скорее всего, вас через две недели;)) от внутренних компонентов. Я работаю над продуктом с теми же проблемами: рендеринг (потенциально больших) карт либо на экран, либо в файлы .bmp.
Спасибо, Роэл. Я думаю, что «разделяй и властвуй» в сочетании с большим растровым кодом Саймона - хорошее долгосрочное решение. Вероятно, с использованием скользящего вертикального сканирования, большого буфера и очистки и повторения, когда и если буфер исчерпан.
Спасибо, Саймон, именно то, что мне нужно. У меня 8 бит на пиксель, так что с этим все в порядке.