AlphaBlend генерирует неправильные цвета

Мне десятилетиями удавалось избегать Windows GDI, и теперь я расплачиваюсь. Следующий код C++ не приводит к правильным цветам. Он просто должен залить окно белым цветом, а затем выполнить альфа-смешение одного растрового изображения. Вся альфа является попиксельной альфой в растровом изображении.

// Create a memory DC
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmMem = CreateCompatibleBitmap(hdc, cxWnd, cyWnd);
SelectObject(hdcMem, hbmMem);

// White-fill the BG
FillRect(hdcMem, &rectWnd, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));

// Alpha blend the bitmap into the memory DC
HDC hdcSrc = CreateCompatibleDC(hdcMem);
HBITMAP hbmOld = static_cast<HBITMAP>(SelectObject(hdcSrc, hbm));
BLENDFUNCTION bfn = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(hdcMem, x, y, cxBmp, cyBmp, hdcSrc, 0, 0, cxBmp, cyBmp, bfn);
SelectObject(hdcSrc, hbmOld);
DeleteDC(hdcSrc);

// Blit the memory DC to the screen
BitBlt(hdc, 0, 0, cxWnd, cyWnd, hdcMem, 0, 0, SRCCOPY);

Я проверил, что все значения переменных верны и что растровое изображение в hbm имеет правильные цвета пикселей и альфа-каналы.

Результат показывает много неправильных цветов, например, синий пиксель с низкой альфой должен быть бледно-голубым, но вместо этого темно-красным. Пиксели с высокой альфой намного ближе к тому, какими они должны быть.

Любая помощь приветствуется. ТИА.


person chrisd    schedule 06.07.2014    source источник
comment
Одна проблема с AlphaBlend заключается в том, что он работает наиболее правильно, когда RGB предварительно умножается на значение A. т.е. растровое изображение никогда не должно иметь R › A или G › A или B › A. В результате этого соглашения полностью прозрачными для RGBA являются все нули, которые являются черными для RGBx, так что, например. вставка прозрачного растрового изображения в Word и экспорт документа Word в формате PDF приводит к появлению черных областей там, где растровое изображение должно быть полностью прозрачным.   -  person Cheers and hth. - Alf    schedule 06.07.2014
comment
Помимо предварительного умножения вашего растрового изображения, которое вам нужно сделать, похоже, что ваш источник находится в порядке ABGR, тогда как GDI требует данных пикселей в порядке ARGB. Попробуйте поменять местами значения красного и синего для каждого пикселя.   -  person Jonathan Potter    schedule 06.07.2014
comment
@JonathanPotter: хм, насколько я помню, это неправильно. Я могу ошибаться. но, насколько я помню, формат COLORREF легко читается как RGB... в дампе памяти с прямым порядком байтов.   -  person Cheers and hth. - Alf    schedule 06.07.2014
comment
@Jonathan Potter: значения пикселей были в порядке. Это было предварительное умножение, которого мне не хватало. Увидеть ниже. Спасибо всем.   -  person chrisd    schedule 06.07.2014


Ответы (1)


Ответ из подсказок в комментариях: каждый цветовой канал в каждом пикселе должен быть предварительно умножен на альфа-канал перед смешиванием.

get DIB bits
for each pixel
  r = r * alpha / 255
  g = g * alpha / 255
  b = b * alpha / 255
set DIB bits

MS не позволяет легко найти эти вещи. В единственном образце альфа-смешивания, который я смог найти, нет ни намека на это:

http://msdn.microsoft.com/en-us/library/windows/desktop/dd183353%28v=vs.85%29.aspx

person chrisd    schedule 06.07.2014