在计算机图形中,有两种不同的方法来表示颜色值的不透明度。 Win2D 使用这两种方法。 本文解释两者之间的区别,以及各自用于什么地方。
直通 Alpha
使用直通(也称为线性)alpha 时:
- RGB 值指定正在绘制的内容的颜色
- Alpha 值决定其实体程度
在这个世界上,RGB 和 alpha 是独立的。 可以更改一个,而不会影响另一个。 若要使对象淡出,你将逐渐减少其 alpha 值,同时保持 RGB 不变。
要对两个使用直通 alpha 格式的颜色执行 source-over 混合:
result = (source.RGB * source.A) + (dest.RGB * (1 - source.A))
预乘 Alpha
使用预乘 alpha 时:
- RGB 指定正在绘制的对象为输出结果贡献多少颜色值
- Alpha 值指定它遮挡其后内容的程度
在这个世界中,RGB 和 alpha 是关联的。 若要使对象变得透明,必须同时降低其 RGB 值(以减少颜色贡献)和 alpha 值(以减少对其后方内容的遮挡)。 完全透明对象根本不具有任何颜色,因此只有一个表示 100% 透明度的值:RGB 和 alpha 全部为零。
要对两个使用预乘 alpha 格式的颜色执行 source-over 混合:
result = source.RGB + (dest.RGB * (1 - source.A))
预乘阿尔法用于图形渲染,因为在对图像进行滤波或合成不同图层时,它比普通阿尔法能产生更好的效果。 有关详细信息,请参阅以下博客文章:
Win2D 中的 Alpha
Win2D 在其 API 表面使用直通 alpha,但在内部渲染操作中使用预乘 alpha。
Windows.UI.Color 值使用直通 alpha。 每当你将颜色传递给 Draw* 或 Fill* 方法、设置画笔颜色或清除为颜色值时,此颜色都是使用直通 alpha 指定的。
存储在位图或渲染目标中的像素值,以及对这些表面进行绘制或混合操作,使用预乘 alpha。 从文件中加载位图时,其内容会自动转换为预乘格式。 当你调用 Win2D 绘制方法时,其颜色参数在实际绘制发生前会从直通转换为预乘。
Win2D 图像效果混合使用直通和预乘 alpha。 某些效果对一种格式进行操作,一些效果对另一种格式进行操作,有些则提供一个要选择的属性。 每种效果类型的文档描述了它使用哪种 alpha 模式。 效果输入数据始终假定为预乘,因此当效果需要处理直通 alpha 时,它将首先应用取消预乘转换,计算效果,然后重新预乘输出。
位图 API GetPixelBytes、SetPixelBytes、GetPixelColors 和 SetPixelColors不执行任何 alpha 格式转换。 它们只是直接将位值传输到基础 GPU 纹理或从基础 GPU 纹理传输出来。 这样就可以观察 Win2D 在内部使用哪种 alpha 格式:
- 在 rendertarget 上创建绘图会话
- 调用
drawingSession.Clear(Colors.Transparent) -
Colors.Transparent定义为 R = 255,G = 255,B = 255,A = 0 - Win2D 会将此值转换为预乘格式,生成 R = 0,G = 0,B = 0,A = 0
- 使用
GetPixelColors回读渲染目标的内容 - 观察到它包含预乘格式的 RGB = 0,而不是像原始直通 alpha
Colors.Transparent值那样的 RGB = 255
在 alpha 格式之间转换
要将直通 alpha 颜色值转换为预乘格式,将其 R、G 和 B 值乘以 A。要将预乘转换为直通,将 R、G 和 B 除以 A。
请注意,颜色信息通常表示为从 0 到 255 的字节值(例如 Windows.UI.Color 结构包含 4 个字节)。 这种表示形式按 255 倍进行缩放,因此字节值 255 实际上表示 1,而 128 表示一半强度。 在格式转换期间必须考虑该缩放因子,因此要将 Windows.UI.Color 从直通转换为预乘:
premultiplied.R = (byte)(straight.R * straight.A / 255);
premultiplied.G = (byte)(straight.G * straight.A / 255);
premultiplied.B = (byte)(straight.B * straight.A / 255);
premultiplied.A = straight.A;
如果你有使用错误 alpha 格式的图像数据, PremultiplyEffect 或者 UnPremultiplyEffect 可用于转换它。