c++ - Pixels Overlay With transparency -
i have 2 pixels in b8g8r8a8 (32) format. both pixels (top , bottom) has transparency (alpha channel < 255 )
what way (formula) overlay top pixel on bottom 1 ? (without using 3rd parties).
i tried this
struct fcolor { public: // variables. #if platform_little_endian #ifdef _msc_ver // win32 x86 union { struct{ uint8 b,g,r,a; }; uint32 alignmentdummy; }; #else // linux x86, etc uint8 b gcc_align(4); uint8 g,r,a; #endif #else // platform_little_endian union { struct{ uint8 a,r,g,b; }; uint32 alignmentdummy; }; #endif //... }; forceinline fcolor alphablendcolors(fcolor pixel1, fcolor pixel2) { fcolor blendedcolor; //calculate new alpha: uint8 newalpha = 0; newalpha = pixel1.a + pixel2.a * (255 - pixel1.a); //get fcolor uint32 uint32 colora = pixel1.dwcolor(); uint32 colorb = pixel2.dwcolor(); uint32 rb1 = ((0x100 - newalpha) * (colora & 0xff00ff)) >> 8; uint32 rb2 = (newalpha * (colorb & 0xff00ff)) >> 8; uint32 g1 = ((0x100 - newalpha) * (colora & 0x00ff00)) >> 8; uint32 g2 = (newalpha * (colorb & 0x00ff00)) >> 8; blendedcolor = fcolor(((rb1 | rb2) & 0xff00ff) + ((g1 | g2) & 0x00ff00)); blendedcolor.a = newalpha; return blendedcolor; }
but result far not want :-)
i looked alpha blending formulas (i did never understand how calculate new alpha of overlay) -> perhaps going in wrong direction ?
edit:
changing newalpha
newalpha = fmath::min(pixel1.a + pixel2.a, 255);
gives better result, right calculate ? missing here?
working example based on accepted answer)
forceinline fcolor alphablendcolors(fcolor bottompixel, fcolor toppixel) { fcolor blendedcolor; //calculate new alpha: float norma1 = 0.003921568627451f * (toppixel.a); float norma2 = 0.003921568627451f * (bottompixel.a); uint8 newalpha = (uint8)((norma1 + norma2 * (1.0f - norma1)) * 255.0f); if (newalpha == 0) { return fcolor(0,0,0,0); } //going straight alpha formula float dstcoef = norma2 * (1.0f - norma1); float multiplier = 255.0f / float(newalpha); blendedcolor.r = (uint8)((toppixel.r * norma1 + bottompixel.r * dstcoef) * multiplier); blendedcolor.g = (uint8)((toppixel.g * norma1 + bottompixel.g * dstcoef) * multiplier); blendedcolor.b = (uint8)((toppixel.b * norma1 + bottompixel.b * dstcoef) * multiplier); blendedcolor.a = newalpha; return blendedcolor; }
start assuming there third pixel below happens opaque.
for further notations, assume alpha values in [0,1].
given: 3 pixels first 1 being on top, colors c_1, c_2, c_3, alpha values a_1, a_2, a_3 = 1
then resulting alpha value 1 , color is
(a_1)*c_1 + (1-a_1)(*a_2)*c_2 + (1-a_1)*(1-a_2)*c_3
now, want find values c_k, a_k formula above equates
(a_k)*c_k + (1-a_k)*c_3
we can solve in 2 steps:
(1-a_k) = (1-a_1)*(1-a_2) -> a_k = 1-(1-a_1)*(1-a_2)
and
(a_k)*c_k = (a_1)*c_1 + (1-a_1)(*a_2)*c_2 -> c_k = [(a_1)*c_1 + (1-a_1)(*a_2)*c_2] / a_k
use formulas (with different range alpha values) , desired color.
(don't forget catch a_k = 0)
edit: explanation of third pixel:
when use 2 pixels in way, doing results in being used display something, put on other existing color opaque. example, might background color, color result of applying many more transparent pixels on background color.
what combine 2 colors find color behaves 2 colors. is, putting on top of opaque color should result in same putting original 2 colors on top of it. demand of new color, resulting in formula use.
the formula nothing result of applying 2 colors in succession on third one.
Comments
Post a Comment