gpt4 book ai didi

c# - 预乘 alpha 合成

转载 作者:行者123 更新时间:2023-11-30 14:18:13 30 4
gpt4 key购买 nike

我正在尝试实现预乘 alpha 混合。在这个页面上:What Is Color Blending? ,他们确实解释了标准的 alpha 混合,但没有解释预乘值。

Alpha 混合:(源 × Blend.SourceAlpha)+(目标 × Blend.InvSourceAlpha)

根据公式,它转化为:

  a = ((srcA * srcA) >> 8) + ((tgtA * (255 - srcA)) >> 8);
r = ((srcR * srcA) >> 8) + ((tgtR * (255 - srcA)) >> 8);
g = ((srcG * srcA) >> 8) + ((tgtG * (255 - srcA)) >> 8);
b = ((srcB * srcA) >> 8) + ((tgtB * (255 - srcA)) >> 8);

它有效,显然......

现在如何将其转换为处理预乘值?

  a = ((srcA)) + ((tgtA * (255 - srcA)) >> 8);
r = ((srcR)) + ((tgtR * (255 - srcA)) >> 8);
g = ((srcG)) + ((tgtG * (255 - srcA)) >> 8);
b = ((srcB)) + ((tgtB * (255 - srcA)) >> 8);

因为它已经被预乘,所以我放弃了第一项的乘法……对吧!?但结果介于alpha blending和additive blending之间,更倾向于additive。最后它看起来并不太混合。这可能是错误的,因为它看起来应该与经典的 alpha 混合完全一样;或者这是预期的行为?

谢谢。

最佳答案

预乘起作用的原因是它实际上在将源图像添加到目标之前最终对目标的 alpha 进行平方

例如。没有预乘,我们得到源图像数据:

srcA = origA
srcR = origR
srcG = origG
srcB = origB

当应用于目标时,我们得到的结果图像是这样的:

a = ((srcA * srcA) >> 8) + ((tgtA * (255 - srcA)) >> 8)
r = ((srcR * srcA) >> 8) + ((tgtR * (255 - srcA)) >> 8)
g = ((srcG * srcA) >> 8) + ((tgtG * (255 - srcA)) >> 8)
b = ((srcB * srcA) >> 8) + ((tgtB * (255 - srcA)) >> 8)

将其展开我们得到:

a = ((origA * origA) >> 8) + ((tgtA * (255 - origA)) >> 8)
r = ((origR * origA) >> 8) + ((tgtR * (255 - origA)) >> 8)
g = ((origG * origA) >> 8) + ((tgtG * (255 - origA)) >> 8)
b = ((origB * origA) >> 8) + ((tgtB * (255 - origA)) >> 8)

那里没有惊喜......

现在对于预乘的源图像数据,我们得到:

srcA = (origA * origA) >> 8
srcR = (origR * origA) >> 8
srcG = (origG * origA) >> 8
srcB = (origB * origA) >> 8

当应用于目标时:

a = (srcA >> 8) + ((tgtA * (255 - srcA)) >> 8);
r = (srcR >> 8) + ((tgtR * (255 - srcA)) >> 8);
g = (srcG >> 8) + ((tgtG * (255 - srcA)) >> 8);
b = (srcB >> 8) + ((tgtB * (255 - srcA)) >> 8);

好的,所以我们知道这一点,但如果我们展开它,您会看到不同之处:

a = (origA * origA) >> 8 + ((tgtA * (255 – ((origA * origA) >> 8))) >> 8);
r = (origR * origA) >> 8 + ((tgtR * (255 - ((origA * origA) >> 8))) >> 8);
g = (origG * origA) >> 8 + ((tgtG * (255 – ((origA * origA) >> 8))) >> 8);
b = (origB * origA) >> 8 + ((tgtB * (255 – ((origA * origA) >> 8))) >> 8);

将其与 NON Pre-Multiplied 扩展进行比较:

a = ((origA * origA) >> 8) + ((tgtA * (255 - origA)) >> 8)
r = ((origR * origA) >> 8) + ((tgtR * (255 - origA)) >> 8)
g = ((origG * origA) >> 8) + ((tgtG * (255 - origA)) >> 8)
b = ((origB * origA) >> 8) + ((tgtB * (255 - origA)) >> 8)

您可以立即看到我们在将 origA 值应用于目标时对其进行平方,这意味着更多的目标将通过生成的颜色值。

你说的是平方,我希望实现更多目标。

这就是为什么在预乘时它会消除透明 block 周围的 strip 数量,因为与不进行预乘相比,那些具有较低 Alpha 值的像素会获得更多的目标像素,并且这种情况会以指数方式发生规模。

我希望这能解决问题。

关于c# - 预乘 alpha 合成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4867685/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com