我正在尝试实现预乘α混合。在这个页面上:什么是配色?,他们确实解释了标准的α混合,但不解释前乘值。
α共混:(源×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);由于它被预先乘以,我在第一项中放弃了乘法.对吧!?结果表明,α共混与加性共混更倾向于加性。最后,它看起来并不是太混在一起。这可能是错误的,因为它应该看起来完全像经典的阿尔法混合;或者这是预期的行为?
谢谢。
发布于 2011-06-25 23:45:07
预乘法工作的原因是,在将源图像添加到目标之前,它实际上结束了对目标的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);将其与以下非乘积展开进行比较:
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值应用于目标时,我们正在对其进行平方,这意味着更多的目标将传递到最终的颜色值。
你的意思是,我希望更多的目标通过。
这就是为什么当预乘时,它移除透明块周围的带带数量,因为那些α值较低的像素获得的目标像素比如果不进行预乘时得到的目标像素要多,而且这种情况发生在指数级。
我希望这能把它弄清楚。
发布于 2011-02-01 21:07:00
你所遇到的问题取决于你是否将你的源α值作为预乘法的一部分进行预乘。如果是这样的话,那么您在目标乘法中使用的srcA是实际源Alpha的平方,所以您需要取平方根来进行计算:
originalSrcA = Math.Sqrt(srcA);
a = ((srcA)) + ((tgtA * (255 - originalSrcA)) >> 8);
r = ((srcR)) + ((tgtR * (255 - originalSrcA)) >> 8);
g = ((srcG)) + ((tgtG * (255 - originalSrcA)) >> 8);
b = ((srcB)) + ((tgtB * (255 - originalSrcA)) >> 8);如果没有预乘(我认为这更有可能),则需要自己乘以才能得到与工作结果相同的结果:
a = ((srcA * srcA) >> 8) + ((tgtA * (255 - srcA)) >> 8);
r = ((srcR)) + ((tgtR * (255 - srcA)) >> 8);
g = ((srcG)) + ((tgtG * (255 - srcA)) >> 8);
b = ((srcB)) + ((tgtB * (255 - srcA)) >> 8);发布于 2011-02-01 21:05:15
一个疯狂的猜测:你是否改变了混合的数量(srcA)?如果是这样,则必须在位图中重新计算预乘的alpha值。如果你不这样做,你会得到一个加法效果,这可能是你所描述的。
https://stackoverflow.com/questions/4867685
复制相似问题