Reputation: 341
I have a function for blending pixels but the alpha value for the new pixel is wrong. Iv tried a few different approaches too fixing this in the past but could never figure out the correct algorithm for generating the correct alpha value.
An example of what I'm attempting to do. Draw testImage2 over testImage1. The problem may not be obvious when viewing the images on stackoverflow depending on the background color. Try viewing the images with an actual image viewer.
Would prefer to have a solution that doesn't use float or double types. The first parameter is a pointer to the background pixel while the second parameter is the actual pixel value of the front pixel. The 3rd parameter just adjusts the alpha value for the entire pixel.
testImage1:
testImage2:
Expected result:
Actual result:
The code:
struct PIXEL
{
unsigned char Blue;
unsigned char Green;
unsigned char Red;
unsigned char Alpha;
};
void RenderAlphaPixel(PIXEL* pDestination, U32 Color, unsigned char Alpha)
{
signed int Alpha2, Remainder, Red, Green, Blue, Alpha3;
Alpha2 = (Color >> (8 * offsetof(PIXEL, Alpha)));
Alpha2 -= 255;
Alpha2 += Alpha;
if (Alpha2 < 0) Alpha2 = 0;
Remainder = 255 - Alpha2;
Red = (unsigned char)(Color >> (8 * offsetof(PIXEL, Red)));
Green = (unsigned char)(Color >> (8 * offsetof(PIXEL, Green)));
Blue = (unsigned char)(Color >> (8 * offsetof(PIXEL, Blue)));
Alpha3 = (unsigned char)(Color >> (8 * offsetof(PIXEL, Alpha)));
pDestination->Red = (unsigned char)(((pDestination->Red * Remainder) + (Red * Alpha2)) / 255);
pDestination->Green = (unsigned char)(((pDestination->Green * Remainder) + (Green * Alpha2)) / 255);
pDestination->Blue = (unsigned char)(((pDestination->Blue * Remainder) + (Blue * Alpha2)) / 255);
// todo. Fix me!
pDestination->Alpha = (unsigned char)(((pDestination->Alpha * Remainder) + (Alpha3 * Alpha2)) / 255);
}
EDIT for WENDYN
When decreasing the alpha of the front image the image becomes very dark. Easy to see the problem when viewing in windows photo viewer.
Expected result:
Actual result:
Upvotes: 1
Views: 491
Reputation: 740
I'd try
vec4 A, B;
out.rgb = A.rgb * A.a + B.rgb * (1.0 - A.a) * B.a;
out.a = A.a + B.a * (1.0 - A.a)
translated to 8 bit channels:
U8 aR, aG, aB, aA;
U8 bR, bG, bB, bA;
cR = ((U16)aR * aA + (U16)bR * (255 - aA) / 255 * bA) / 255;
cG = ((U16)aG * aA + (U16)bG * (255 - aA) / 255 * bA) / 255;
cB = ((U16)aB * aA + (U16)bB * (255 - aA) / 255 * bA) / 255;
cA = aA + (U16)bA * (255 - aA) / 255;
Upvotes: 2