混合像素(为混合像素获取新 alpha 值的正确方法)

Blend Pixel (Correct way to get a new alpha value for a blended pixel)

我有一个混合像素的函数,但是新像素的 alpha 值是错误的。我过去也尝试过几种不同的方法来解决这个问题,但始终无法找出生成正确 alpha 值的正确算法。

我正在尝试做的一个例子。在 testImage1 上绘制 testImage2。 根据背景颜色,在 Whosebug 上查看图像时,问题可能并不明显。尝试使用实际的图像查看器查看图像。

希望有一个不使用 float 或 double 类型的解决方案。第一个参数是指向背景像素的指针,第二个参数是前面像素的实际像素值。第三个参数只是调整整个像素的alpha值。

testImage1:

testImage2:

预期结果:

实际结果:

代码:

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);
}

编辑 WENDYN

当降低正面图像的 alpha 时,图像变得非常暗。在 windows 照片查看器中查看时很容易看到问题。

预期结果:

实际结果:

我会试试

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)

转换为 8 位通道:

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;