使用FreeType渲染的带有颜色和透明度的文本混合

3
我正在使用FreeType渲染一些文本。
我想要绘制文本的表面是一张带有ARGB格式、预乘alpha的位图图像。
所需文本的颜色也是ARGB。
渲染的FT_Bitmap的格式为FT_PIXEL_MODE_LCD - 就好像文本是在黑色背景上用白色渲染的,具有亚像素抗锯齿效果。
因此,对于每个像素,我有三个数字: Da,Dr,Dg,Db - 目标像素ARGB(背景图片)。 Fr,Fg,Fb - FreeType渲染像素(用FT_RENDER_MODE_LCD渲染的FT_Bitmap)。 Ca,Cr,Cg,Cb - 我想要使用的文本的颜色。
所以问题是:如何正确地组合这3个数字以获得结果位图像素。
理论答案比代码示例更好。
2个回答

3

把 FreeType 数据解释成目标文本颜色的强度值,而不是实际的 RGB 颜色(这些“原始”值用于绘制黑色文本)。

因此,每个 F 色彩组件的完整强度为 F*C/255。然而,由于你的 C 还包括一个 alpha 组件,因此强度会按比例缩放:

 s' = F*C*A/(255 * 255)

假设FCA都在0到255的通常范围内。其中,A是一个小数A/255,第二个除法是为了将F*C带回目标范围内。s'现在是派生的源颜色。

接下来是绘图。对于每个颜色分量,新颜色会加到D上,而D则会被源颜色的alpha值255-A(按比例缩放)减少。

这就导致了完整的总和。

D' = D*(255-A)/255 + F*C*A/(255 * 255)

等于(将一个值向右移动)
D' = (D*(255-A) + F*C*A/255)/255

针对DFCA的每个单独通道r、g、b,都需要进行单独计算。由于FreeType输出数据返回此格式,最后一个alpha通道也需要单独计算。

如果计算速度太慢,您可以将视觉结果与未经LCD优化的FreeType灰度输出进行比较。我怀疑特别是在“繁忙”的(不完全单色)背景上,额外的计算根本不值得。
纯灰度输入的数值优势在于,您只需为每个RGB颜色三元组计算一次A1-A

“背景”也具有alpha通道,但要将文本“绘制”到其上,您可以将其视为“未使用”。将透明项绘制到另一个透明项上通常不会改变其固有透明度。


1
A是哪个字母?是背景(目标)- Da还是颜色- Ca? - johnfound
这个答案完全是错误的,因为它根本没有考虑子像素着色。一个测试是将文本呈现为黑色在白色背景上,而不是FreeType返回的白色文本在黑色背景上。 - Mark Ransom
@Jongware D - 目标(背景)具有 alpha 通道,需要它以便稍后与其他图像混合。 - johnfound
@Jongware 用纯黑色(1, 0, 0, 0)在100%透明背景(0, 0, 0, 0)上绘制,然后将其与其他图像混合,这样怎么样? - johnfound
@johnfound:对于置于透明度之上的透明度,有不同的解释。也许你正在寻找 max(Asrc,Adest)(只使 dest 更少透明,永远不会更多)。 - Jongware
显示剩余6条评论

1
在一番探索后,我找到了正确的答案。但是令人失望的是,无法在RGBA格式的透明图像上绘制亚像素渲染的图形(包括字体)。
为了正确渲染此类图形,必须使用支持每种颜色分别具有alpha通道的格式。
例如,每像素48位:RrGgBg,其中r、g和b分别为红、绿和蓝色通道的alpha通道。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接