Как создать монохромную битовую маску для 32-битного растрового изображения - PullRequest
8 голосов
/ 15 октября 2010

Под Win32 это обычная техника для генерации монохромной битовой маски из битовой карты для использования прозрачности, выполняя следующие действия:

SetBkColor(hdcSource, clrTransparency);
VERIFY(BitBlt(hdcMask, 0, 0, bm.bmWidth, bm.bmHeight, hdcSource, 0, 0, SRCCOPY));

Это предполагает, что hdcSource является DC памяти, содержащим исходное изображение, иhdcMask - это DC памяти, содержащий монохромное растровое изображение одинакового размера (поэтому оба имеют размер 32x32, но источник имеет 4-битный цвет, а цель - 1-битный монохромный).

Однако, мне кажется, что это не работает, когдаИсточник 32-битный цвет + альфа.Вместо монохромного растрового изображения в hdcMask, я получаю маску, которая полностью черная.Биты не устанавливаются в белый цвет (1).Принимая во внимание, что это работает для 4-битного источника цвета.

Мой search-foo не работает, так как я не могу найти никаких ссылок на эту конкретную проблему.

Я выделил, что это действительно проблемав моем коде: т.е. если я использую исходное растровое изображение 16 цветов (4 бита), оно работает;если я использую 32-битное изображение, оно создает полностью черную маску.

Есть ли альтернативный метод, который я должен использовать в случае 32-битных цветных изображений?Есть ли проблема с альфа-каналом, который перекрывает нормальное поведение вышеупомянутой техники?

Спасибо за любую помощь, которую вы можете предложить!

ДОБАВЛЕНИЕ: Я все еще не могу найти техникуэто создает действительное монохромное растровое изображение для моего исходного растрового изображения, созданного в GDI +.

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

Может быть полезно иметь действительно хорошую работающую функцию:

HBITMAP CreateTransparencyMask(HDC hdc, HBITMAP hSource, COLORREF crTransparency);

Где всегда создается действительная маска прозрачности, независимо от глубины цвета hSource.

Ответы [ 4 ]

3 голосов
/ 02 января 2011

Можно сделать :)
Как указано выше «Крисом Бекке», GDI может сравнивать, только если зарезервированный альфа-канал равен нулю.
HBITMAP, полученный из BITMAP :: GetHBITMAP (), возвращает HBITMAP с альфа-каналом, все из которых установлены в 0xFF. > Для работы сравнения SetBkColor () это должно быть 0x00.
Следовательно, Soln: перебирает каждый пиксель и устанавливает альфа-компонент на ноль.

Bitmap img(L"X.bmp");
HBITMAP hBM;
img.GetHBITMAP(Color::White, &hBM);
BITMAP bm;
GetObject(g_hbmBall, sizeof(BITMAP), &bm);
for(UINT i = 0, n = -1; i &lt bm.bmHeight; i++)
    for(UINT j = 0; j &lt bm.bmWidth; j++)
    {
        n += 4; // Once per Pixel of 4 Bytes
        ((LPBYTE)bm.bmBits)[n] = 0;
    }<br />
// Now SetBkColor and BitBlt will work as expected
3 голосов
/ 15 октября 2010

Вы не можете сделать это, если есть альфа-канал.COLORREF используют верхние 8 битов для ряда целей, включая указание более или менее младших 3-х байтов, указателя таблицы цветов в текущей палитре или триплета RGB.Таким образом, вы не можете указать ничего, кроме 0x00 в старшем байте clrTransparency.

Если у вас есть альфа-битовое изображение, то для GDI, который остается «неосведомленным» о альфа-канале, нет никакого разумного способа фактически сравнить24-битный BkColor с 32-битными пикселями в растровом изображении.

Я ожидаю, что GDI будет обрабатывать альфа-канал в 32-битных растровых изображениях как «зарезервированный» и только успешно сравнивать пиксели, где зарезервированный канал равен нулю.т. е. цвет вашей маски должен быть полностью прозрачным, чтобы иметь шанс на успех.(и, если вы создали правильное предварительно умноженное растровое изображение, это означает, что значения RGV также будут равны нулю, что ограничит ваш выбор цветов маски: P)

1 голос
/ 06 декабря 2012

Метод, который работал для меня, заключался в том, чтобы сначала преобразовать растровое изображение из 32-битного в 24-битное.

1. CreateCompatibleDC
2. CreateDIBSection with 24 as the biBitCount.
3. SelectObject
4. BitBlt from 32bit DC to 24 bit. This removes alpha.
5. BitBlt from 24 bit DC to the monochrome DC works as expected.

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

0 голосов
/ 15 октября 2010

Альтернативным методом было бы сканировать пиксели самостоятельно и генерировать и монохромное растровое изображение на основе исходного цвета (или альфа-источника в сравнении с пороговым значением).

Обратите внимание, что если вы используете GDI +, то, в зависимости отво время операции пиксели могут быть сглажены, в результате чего ни один из них не будет точным совпадением для вашего "прозрачного" цвета.

...