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

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

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

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

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

Какие-нибудь мысли?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
5 603
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Это необычно, поскольку я часто создавал 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));

Спасибо, Саймон, именно то, что мне нужно. У меня 8 бит на пиксель, так что с этим все в порядке.

SmacL 26.09.2008 12:18

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

Пример:

глубина пикселя = 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 позже.

SmacL 26.09.2008 12:21

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

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

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

Спасибо, Роэл. Я думаю, что «разделяй и властвуй» в сочетании с большим растровым кодом Саймона - хорошее долгосрочное решение. Вероятно, с использованием скользящего вертикального сканирования, большого буфера и очистки и повторения, когда и если буфер исчерпан.

SmacL 27.09.2008 12:24

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