Сохранение растровых изображений в Windows 10 с активным масштабированием GDI - PullRequest
0 голосов
/ 04 июля 2018

У меня есть приложение MFC с панелями инструментов (используя CMFCToolbar). Я создаю растровое изображение панели инструментов на лету, используя растровые изображения из файлов и ресурсов. DIB имеют разные цветовые форматы.

  • Итак, я создаю пустое растровое изображение панели инструментов, совместимое с экраном DC.
  • Затем я открываю все растровые изображения и помещаю содержимое в растровое изображение панели инструментов (GDI выполняет преобразование и растяжение цветового пространства для меня).
  • Затем я сохраняю растровое изображение в 24-битном DIB-файле.
  • Затем я создаю объект панели инструментов и загружаю изображение.

Это работало целую вечность и работает сейчас, за исключением одного случая:

Недавно нам пришлось включить масштабирование GDI для Windows 10 1703 и более поздних версий. В системе с дисплеем с высоким разрешением и масштабированием 200% (например, Surface) происходит следующий эффект:

Все значки на панели инструментов искажены.

Я также нашел причину:

При сохранении составного изображения я получаю только верхнюю левую четверть изображения. Ширина и высота растрового изображения не изменились (скажем, 1024x15) по сравнению с обычным разрешением экрана без масштабирования GDI. Но это растровое изображение содержит только пиксели верхней левой четверти (см. Пример ниже).

Итак, я предполагаю, что контекст устройства сообщает Windows о 200% масштабировании. При перемещении от источника к цели изображение автоматически увеличивается, но размер растрового изображения не изменяется.

Как сохранить немасштабированное растровое изображение?

-или-

Как правильно сохранить масштабированное растровое изображение? Где взять недостающие пиксели? Где взять правильные размеры? (HBITMAP относится только к немасштабированным размерам).

Пример: * * тысяча тридцать-один

без масштабирования GDI, правильно:

no scaling

200% масштабирования, те же размеры, но только верхняя левая четверть правильного изображения:

with 200 scaling

1 Ответ

0 голосов
/ 09 июля 2018

Сводка и решение:

Допустим, мы создаем растровое изображение памяти, совместимое с форматом экрана (DDB):

CBitmap toolBitmap;
toolBitmap.CreateCompatibleBitmap (pDC, 1000, 20);

Позже мы добавляем что-то в растровое изображение памяти (здесь не имеет значения) Теперь мы хотим сохранить растровое изображение (записать в файл как DIB).

Хотя мы знаем размеры (здесь: 1000x20) , мы не должны их использовать . Поскольку в Window 10 и process активировано масштабирование GDI и используется отображение с высоким разрешением с масштабированием - размеры могли измениться внутри. Таким образом, растровое изображение больше не 1000x20.

Этот сбой:

BITMAP bmHdr;
toolBitmap.GetObject(sizeof(BITMAP), &bmHdr);

Заголовок растрового изображения содержит исходные размеры (1000x20). Использование их для сохранения в файл приводит к неполному изображению . Будет сохранена только верхняя левая часть.

Этот работает - мы можем получить масштабированные размеры:

BITMAPINFO bi = {};
bi.dwSize = sizeof(bi);
int result = GetDIBits(pDC->GetSafeHdc(), (HBITMAP)toolBitmap.GetSafeHandle(), 0, 0, NULL, &bi, DIB_RGB_COLORS);

Теперь мы можем приступить к новым измерениям.

В итоге я использовал функции GDI +, которые также сохраняют полное (масштабированное) растровое изображение:

Gdiplus::Bitmap bm((HBITMAP)toolBitmap.GetSafeHandle(), NULL);
Gdiplus::Status status = bm.Save(pwszFileName, &clsidEncoder, NULL);

Я предполагаю, что есть тонны старого кода MFC и GDI, которые не будут работать правильно с активированным масштабированием GDI в Windows 10.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...