混合像素(为混合像素获取新 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;
我有一个混合像素的函数,但是新像素的 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;