Понимание AlphaBlending в Windows

У меня есть растровое изображение 32bpp, которое имеет альфа-канал со значениями в диапазоне от 0 до 255. Я пытаюсь отобразить это в окне, используя API-интерфейсы win32 (прилагается фрагмент кода, который я использую для отображения).

Я читал документацию, и оказалось, что для смешивания, в случае, когда я хочу использовать попиксельные значения, окна используют следующую формулу:

Dst.Red     = Src.Red   + (1 - Src.Alpha) * Dst.Red
Dst.Green   = Src.Green + (1 - Src.Alpha) * Dst.Green
Dst.Blue    = Src.Blue  + (1 - Src.Alpha) * Dst.Blue

Это странно. Я ожидал, что он будет использовать:

Dst.Red     =  Src.Alpha*Src.Red    + (1 - Src.Alpha) * Dst.Red
Dst.Green   =  Src.Alpha*Src.Green  + (1 - Src.Alpha) * Dst.Green
Dst.Blue    =  Src.Alpha*Src.Blue   + (1 - Src.Alpha) * Dst.Blue

потому что именно это создает эффект наложения (полупрозрачности).

Правильно ли мое ожидание? Если да, то почему Windows выполняет смешивание таким образом? Что мне здесь не хватает?

фрагмент кода, который я использую для рисования многослойного окна:

            bf.BlendOp = AC_SRC_OVER;
            bf.BlendFlags = 0;
            bf.SourceConstantAlpha = 255;  
            bf.AlphaFormat = AC_SRC_ALPHA;              
            POINT ptOrigin = { 0, 0 };
            SIZE windowSize = { 300, 300 };

            POINT ptZero = { 0, 0 };

            UpdateLayeredWindow(m_sThis->m_hWnd, dc, &ptOrigin, &windowSize,
                hdc, &ptZero, RGB(255, 255, 255), &bf, ULW_ALPHA);

person TheBlueNotebook    schedule 12.01.2016    source источник


Ответы (1)


Из документации:

Обратите внимание, что API-интерфейсы используют предварительное умножение альфа-канала, что означает, что значения красного, зеленого и синего каналов в растровом изображении должны быть предварительно умножены на значение альфа-канала. Например, если значение альфа-канала равно x, красный, зеленый и синий каналы должны быть умножены на x и разделены на 0xff перед вызовом.

Итак, вы правы, но вы должны сделать это вручную раньше.

person Martin Bonner supports Monica    schedule 12.01.2016
comment
Ах. Предварительное умножение теперь имеет смысл. Но зачем им держать это в таком виде? - person TheBlueNotebook; 12.01.2016
comment
Я написал в пост наверное. Еще раз из документации: есть веская причина, по которой он использует предварительно умноженную альфу. Просто неэффективно умножать исходный цвет на исходную альфу каждый раз для каждого пикселя. Это нужно сделать только один раз, так как значения цвета и альфа коррелируют. Обычно это делается во время создания изображения (например, PNG использует альфа-канал с предварительным умножением) и позволяет сэкономить очень дорогостоящее умножение для каждого пикселя при каждом рисовании. - person TheBlueNotebook; 12.01.2016