Ручное альфа-смешивание пикселя RGBA с пикселем RGB

Я пытаюсь выполнить операцию альфа-смешивания изображения RGBA (изображение переднего плана) на изображение RGB (фоновое изображение). Однако при этом я думаю, что, возможно, выполняю неправильную операцию альфа-смешивания или делаю это неправильно. Например, пиксель моего изображения RGB сероватого цвета (127, 127, 127). Пиксель моего изображения RGBA для пикселя будет (0, 0, 255). После того, как я выполню операцию смешивания, окончательный цвет будет (127, 0, 255). Однако я подумал, что это скорее смесь добавок и отличная от той операции, которую я выполняю.

Чтобы узнать, как устанавливаются мои значения, взгляните на это

incPixelColor[0] = 0; (red)
incPixelColor[1] = 0; (green)
incPixelColor[2] = 255; (blue)
incPixelColor[3] = 255; (alpha)

currentPixelColor[0] = 127; (red)
currentPixelColor[1] = 127; (green)
currentPixelColor[2] = 127; (blue)

Чтобы узнать, как устроен мой расчет, взгляните на это

float incAlpha = (currentPixelColor[3]/255.0f);

float red = ((float)incPixelColor[0]/255.0f * incAlpha) + ((float)currentPixelColor[0]/255.0f);
float green = ((float)incPixelColor[1]/255.0f * incAlpha) + ((float)currentPixelColor[1]/255.0f);
float blue = ((float)incPixelColor[2]/255.0f * incAlpha) + ((float)currentPixelColor[2]/255.0f);


currentPixelColor[0] = min(red * 255, 255.0f);
currentPixelColor[1] = min(green * 255, 255.0f);
currentPixelColor[2] = min(blue * 255, 255.0f);

Для пикселей без альфа-канала я бы хотел, чтобы значение было (0, 0, 255), тогда для изображений с альфа-каналом я бы хотел, чтобы он сливался. В конце операции, описанной выше, это будет (127, 127 , 255). Должен ли я проверить, есть ли альфа для каждого пикселя, и если да, то сделать смешивание или есть другой способ сделать это?


comment
Вы делаете аддитивное смешивание. Рассмотрим линейное перемешивание следующим образом: y = (x0 * w) + (x1 * (1-w))   -  person Osman Turan    schedule 26.01.2012
comment
Это много 255 масштабирования вперед и назад. В этом нет необходимости, если ваши операции поддерживают нормализацию.   -  person fche    schedule 26.01.2012


Ответы (3)


Типичное смешивание "Over" выполняется следующим образом:

outputRed = (foregroundRed * foregroundAlpha) + (backgroundRed * (1.0 - foregroundAlpha));

А затем повторить для синего и зеленого каналов. Сделайте это для каждого пикселя.

person user1118321    schedule 26.01.2012
comment
Возможно, я ошибаюсь, но разве я не этим уже занимаюсь? - person mmurphy; 26.01.2012
comment
Нет, вы делаете outputRed = (foreRed * foreAlpha) + backgroundRed. Вам нужно умножить backgroundRed на (1.0 - foreAlpha). - person user1118321; 26.01.2012
comment
Извините, что так поздно, но что произойдет с альфа-каналом выходного альфа-канала, если и целевые, и исходные пиксели прозрачны? - person Vlas Bashynskyi; 28.07.2014
comment
Он тоже становится прозрачным. Поэтому, если у вас есть исходный пиксель с 0% покрытием (альфа), он не должен вносить вклад в вывод. Если вы наложите это на пиксель с 0% покрытием, фон также не должен влиять на результат. Таким образом, результат будет RGBA = (0,0,0,0). Он будет, так сказать, прозрачно-черным. Если вы наложите результат на что-то непрозрачное, вы увидите все, на что вы его наложили. - person user1118321; 28.07.2014
comment
Предполагается ли, что foregroundAlpha находится в диапазоне 0–255 или 0–1? - person Julian; 09.08.2016
comment
Предполагается, что альфа находится в диапазоне 0-1. - person user1118321; 10.08.2016
comment
Эта формула превращает 50% красного цвета на белом фоне в rgb(255, 128, 128), что является математически правильным. В macOS я заметил, что Chrome, Safari и даже Sketch App смешивают эту настройку с rgb(255, 138, 138). Firefox rgb(255, 126, 124). Однако Photoshop придерживается 128-го. Интересно, что некоторые программы по каким-либо причинам предпринимают дополнительные шаги, и 50% красного не всегда 50% красного Pen: codepen.io/timohausmann/pen/rNLdpwJ?editors=0100 Снимок экрана macOS: imgur.com/ a / 2ioPPiy - person Ti Hausmann; 30.10.2020

Похоже, вы пропустили множитель (1-Alpha) для фона (currentPixelColor)

person MBo    schedule 26.01.2012

alpha_blend_sse :)

;example usage
;mov eax, 0xabcdef
;mov edx, 0xAAAAAADD
;call alph_blend_see


; In\   EAX = background color (ZRBG) 32bit (Z mean zero, always is zero)
; In\   EDX = foreground color (RBGA) 32bit
; Out\  EAX = new color
alph_blend_sse:
    xor r14, r14
    xor r12, r12
    xor r13, r13

    movzx r15, dl               ; av: alpha number (0x00--->0xFF)
    movzx ecx, dl
    not ecx                     ; faster than 255 - dl
    mov r14b, cl                ; rem

    shr edx, 8
    and edx, 0x00FFFFFF
    mov r12d, edx
    mov r13d, eax               ; RBGA ---> ZRGB

    mov rax, 0x0000FF
    movq xmm3, rax

    ; s: eax
    ; d: edx

    ;=============================red = ((s >> 16) * rem + (d >> 16) * av) >> 8;
    movq xmm0, r12
    psrld xmm0, 0x10
    movq xmm1, r14
    pmuludq xmm1, xmm0
    movq xmm0, r13
    psrld xmm0, 0x10
    movq xmm2, r15
    pmuludq xmm2, xmm0
    addps xmm2, xmm1
    psrld xmm2, 0x8
    movq rax, xmm2
    mov r9b, al
    shl r9d, 8

    ;=============================green = (((s >> 8) & 0x0000ff) * rem + ((d >> 8) & 0x0000ff) * av) >> 8;
    movq xmm0, r12
    psrld xmm0, 0x8
    andps xmm0, xmm3
    movq xmm1, r14
    pmuludq xmm1, xmm0
    movq xmm0, r13
    psrld xmm0, 0x8
    andps xmm0, xmm3
    movq xmm2, r15
    pmuludq xmm2, xmm0
    addps xmm2, xmm1
    psrld xmm2, 0x8
    movq rax, xmm2
    mov r9b, al
    shl r9d, 8

    ;=============================blue = ((s & 0x0000ff) * rem + (d & 0x0000ff) * av) >> 8;
    movq xmm0, r12
    andps xmm0, xmm3
    movq xmm1, r14
    andps xmm1, xmm3
    pmuludq xmm1, xmm0
    movq xmm0, r13
    andps xmm0, xmm3
    movq xmm2, r15
    andps xmm2, xmm3
    pmuludq xmm2, xmm0
    addps xmm2, xmm1
    psrld xmm2, 0x8
    movq rax, xmm2
    mov r9b, al

    mov eax, r9d
    ret
person Mahdi Mohammadi    schedule 13.04.2018