Как создать очень большое растровое изображение в C++/MFC/GDI

StackOverflow https://stackoverflow.com/questions/138122

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Есть предположения?

Это было полезно?

Решение

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

Вероятно, вам не повезет с разрешением 20 000 x 20 000 при 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));

Другие советы

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

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

Пример:

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

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

общее количество байт = количество пикселей * 4 = 1 600 000 000 байт = 1 562 500 КБ ~= 1525 МБ ~= 1,5 ГБ

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

удачи

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top