Как создать очень большой точечный рисунок в C ++ / MFC / GDI - PullRequest
1 голос
/ 26 сентября 2008

Я хотел бы иметь возможность создавать растровое растровое изображение (скажем, 20 000 x 20000) в приложении C ++ MFC, используя производный от CDC класс для записи в растровое изображение. Я попытался использовать контроллеры памяти, как описано в документах MSDN, но, похоже, они ограничены размерами, совместимыми с текущим драйвером дисплея.

В настоящее время я использую драйвер растровой печати для выполнения этой работы, но он чрезвычайно медленный и использует очень большие объемы промежуточного хранилища из-за спулинга информации GDI.

Решение, которое я ищу, не должно включать метафайлы или буферизацию, так как модель, которую я рисую, требует много миллионов вызовов GDI для рендеринга.

Я мог бы использовать подход «разделяй и властвуй» через несколько контроллеров памяти, но это кажется довольно громоздким и неэлегичным методом.

есть мысли?

Ответы [ 5 ]

2 голосов
/ 26 сентября 2008

CDC и CBitmap, по-видимому, поддерживают только зависящие от устройства растровые изображения. Возможно, вам больше повезет, если вы создадите свое растровое изображение с помощью :: CreateDIBSection , а затем добавите к нему CBitmap. Сырые интерфейсы GDI, к сожалению, немного седые.

Вероятно, вам не очень повезет с 20 000 x 20 000 при 32 BPP, по крайней мере, в 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));
1 голос
/ 26 сентября 2008

Чтобы сохранить использование памяти в допустимых пределах, вам придется использовать стратегию «разделяй и властвуй». Это не хак, если реализовано правильно, это на самом деле очень элегантный способ работы с растровыми изображениями неограниченного размера. Если вы спроектируете это правильно, вы можете объединить «рендеринг / показать часть изображения», «рендеринг всего изображения с низким разрешением для отображения на экране» и «рендеринг всего объекта в растровое изображение на диске» один движок и оградит пользователей вашего кода (скорее всего от вас самих через две недели;)) от внутренних органов. Я работаю над продуктом с теми же проблемами: рендеринг (потенциально больших) карт на экране или в файлах .bmp.

1 голос
/ 26 сентября 2008

Учитывая такое большое разрешение изображения, вы не можете создать изображение с помощью совместимых растровых изображений.

Пример:

глубина пикселя = 32 бита = 4 байта на пиксель

количество пикселей = 20.000 * 20.000 = 400.000.000

общее количество байтов = количество пикселей * 4 = 1.600.000.000 байтов = 1.562.500 кбайт = = 1525 МБ ~ = 1.5ГБ

Я размышляю об окончательных намерениях, но предположим, что вы хотите создать и позволить пользователям исследовать огромную карту с очень подробным увеличением. Вы должны создать собственный формат файла изображения; Вы можете поместить в этот файл различные слои, содержащие сетки растровых изображений, например, для ускорения рендеринга. Процесс рендеринга может использовать GDI DIB или GDI + для создания частичных изображений, а затем рендерить их вместе. Конечно, для достижения идеального ощущения пользователя нужно немного поэкспериментировать / оптимизировать.

удачи

1 голос
/ 26 сентября 2008

Это необычно, поскольку я часто создавал DC на основе экрана, который будет использоваться для растрового изображения, которое намного больше экрана - 3000 пикселей плюс в некоторых случаях - без каких-либо проблем. У вас есть пример кода, показывающий эту проблему в действии?

0 голосов
/ 26 сентября 2008

Если изображение должно соответствовать этому разрешению, скажем, при сканировании рентгеновского снимка в высоком разрешении, возможно, вы захотите написать для него специальные процедуры буферизации - 1,5 ГБ очень дорого - даже для современных настольных компьютеров.

Если это вектор, то вы можете взглянуть на SVG, так как он поддерживает порты просмотра и большинство позволяет рендерить в другие форматы. Я использую SVG для JPG через батик (Java), так что это можно сделать.

...