如何在手动“叠加”混合操作中处理 alpha?
Posted
技术标签:
【中文标题】如何在手动“叠加”混合操作中处理 alpha?【英文标题】:How to handle alpha in a manual "Overlay" blend operation? 【发布时间】:2011-01-14 08:13:16 【问题描述】:我正在使用一些手动(逐像素)图像处理,并且我正在重新创建标准的“叠加”混合。我在这里查看“Photoshop 数学”宏:
http://www.nathanm.com/photoshop-blending-math/ (See also here 更易读的 Overlay 版本)
两个源图像都采用相当标准的 RGBA(每个 8 位)格式,目标图像也是如此。当两个图像都完全不透明(alpha 为 1.0)时,结果会按预期正确混合:
但是,如果我的“混合”图层(顶部图像)具有透明度,那么对于 如何正确地将 alpha 因素纳入混合方程,我会感到有些困惑。我希望它能够工作,这样混合层中的透明像素对结果没有影响,混合层中的不透明像素正常进行覆盖混合,而半透明混合层像素对结果有一些缩放效果。
有人可以向我解释一下混合方程式或这样做背后的概念吗?
加分如果您能帮我做到这一点,以使生成的图像具有正确的预乘 alpha(我认为这只对两个图层中不透明的像素起作用。)
谢谢!
// factor in blendLayerA, (1-blendLayerA) somehow?
resultR = ChannelBlend_Overlay(baseLayerR, blendLayerR);
resultG = ChannelBlend_Overlay(baseLayerG, blendLayerG);
resultB = ChannelBlend_Overlay(baseLayerB, blendLayerB);
resultA = 1.0; // also, what should this be??
【问题讨论】:
【参考方案1】:混合基色和混合色后,使用混合色的 alpha 混合原始基色和混合产生的颜色:
vec4 baseColor = ...;
vec4 blendColor = ...;
vec4 blendedColor = blend(baseColor, blendColor);
vec4 fragmentColor = (1.0 - blendColor.a) * baseColor + blendColor.a * blendedColor;
我用它来“叠加”混合不透明的基色和具有大量(半)透明像素的混合纹理。
【讨论】:
【参考方案2】:只是猜测,但我会尝试
resultA = 1 - (1-baseAlpha) * (1-blendAlpha)
【讨论】:
好的,这是什么原理?谢谢。 @quixoto 好吧,我想将两者相乘以使它们都在等式中,而不会在组合透明层时过早达到不透明度(添加它们时会发生这种情况)。但是简单地相乘会使它接近于零,其中一个接近于零。因此,我将整个事情颠倒过来,测试值(如 0、0.5、1)“感觉还可以”【参考方案3】:我一直在试验这个问题,直到我发现最好的方法是让基础层和混合层都使用直接 alpha,然后只用基础 alpha 预乘结果。
【讨论】:
【参考方案4】:这很好用,使用这里的公式:https://dev.w3.org/SVG/modules/compositing/master/。我的函数有点古怪,因为它接受一个 0-1 的 DoubleColor 和一个 0-maxValDouble() 的 T* 像素颜色(这是使用的整数类型的最大 val,作为双精度)。
template<typename T> static inline void blendColorOverlay(T* rgba, DoubleColor overColor)
if (overColor.a == 0)
return;
double Da = rgba[3]/maxValDouble<T>();
double Sa = overColor[3];
double Dca, Sca;
double outAlpha = (Sa + Da - Sa*Da);
for (int k = 0; k < 3; k++)
Dca = (rgba[k]/maxValDouble<T>())*Da;
Sca = overColor[k]*Sa;
if (2*Dca <= Da)
rgba[k] = (2*Sca*Dca + Sca*(1.0 - Da) + Dca*(1.0 - Sa))*maxValDouble<T>()/outAlpha;
else
rgba[k] = (Sca*(1.0 + Da) + Dca*(1.0 + Sa) - 2.0*Dca*Sca - Da*Sa)*maxValDouble<T>()/outAlpha;
rgba[3] = outAlpha*maxValDouble<T>();
【讨论】:
以上是关于如何在手动“叠加”混合操作中处理 alpha?的主要内容,如果未能解决你的问题,请参考以下文章