【问题标题】:Blend Pixel (Correct way to get a new alpha value for a blended pixel)混合像素(获取混合像素的新 alpha 值的正确方法)
【发布时间】:2021-08-26 09:12:34
【问题描述】:

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

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

希望有一个不使用 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 照片查看器中查看时很容易看到问题。

预期结果:

实际结果:

【问题讨论】:

  • 两张图片的 alpha 不都是用 Alpha 插值的吗?我认为您不应该将 Color 的 alpha 添加到那里的计算中。

标签: c graphics alphablending


【解决方案1】:

我会试试的

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;

【讨论】:

  • 谢谢! cA = min(255, aA + bA) 似乎已修复它。要使用我的函数bA,必须用Remainder 替换。所以它看起来像这样pDestination-&gt;Alpha = (unsigned char)min(255, Alpha3 + Remainder);
  • 我有一个问题,pDestination-&gt;Alpha 从右侧去哪里了?我很高兴它可以工作,但我不知道如何...不应该是pDestination-&gt;Alpha = min(255, Alpha3 + pDestination-&gt;Alpha)吗?
  • 你是对的,它不起作用。我做了更多的测试并发现了各种问题。仅当我尝试降低整个正面图像的 alpha 状态(调用 RenderAlphaPixel 并将值为 127 作为第三个参数)时,使用您提供的示例才会出现问题,正面图像看起来比我认为的要暗。我将更新问题以显示测试结果。
  • 其实我错了,根据this维基百科的文章也是A.a + B.a * (1.0 - A.a),我已经编辑了我的答案
  • 我能够通过将背景颜色值设置为白色来修复图像变暗的问题,即使像素是透明的,它似乎也会影响结果......结果仍然有点不同(即使使用A.a + B.a * (1.0 - A.a),打印机的阴影也会消失并且边缘很粗糙)。我会进行更多测试并阅读更多内容,看看是否能找到问题所在。
猜你喜欢
  • 2015-01-08
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 2010-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多