加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 预乘alpha合成

发布时间:2020-12-16 01:40:57 所属栏目:百科 来源:网络整理
导读:我正在尝试实现预乘的alpha混合.在这个页面上: What Is Color Blending?,它们确实解释了标准的alpha混合,但没有解释预乘的值. Alpha混合:(来源×Blend.SourceAlpha)(目的地×Blend.InvSourceAlpha) 根据公式,它转换为: a = ((srcA * srcA) 8) + ((tgtA * (
我正在尝试实现预乘的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混合;或者这是预期的行为?

谢谢.

解决方法

预乘的原因是因为在将源图像添加到目标之前,它实际上最终会对目标的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值应用到目标时对其进行平方,这意味着更多的目标将通过生成的颜色值.

通过对你说,你想要更多的目标来实现.

这就是为什么在预乘时它会消除透明块周围的条带数量,因为具有较低Alpha值的像素获得的目标像素数比未预先相乘的情况多得多,而且这种情况以指数级进行.

我希望这能搞清楚.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读