我正在编写自己的TrueType字体光栅化程序,以提高我在计算机图形学(以及基本的矢量图形引擎)方面的知识。在这个阶段,我已经实现了大多数TTF文件解析,解码字形轮廓,缩放和扫描以将轮廓转换为位图。
(我暂时没有进行任何字体提示/网格拟合)。

在反锯齿字形位图时,通常使用什么过程或方法(或最好)?到目前为止,我已经尝试了两种方法。根据轮廓的像素覆盖率,对边缘进行双线性过滤并设置alpha值。

双线性采样太模糊,无法在字体渲染中有效,并且使用像素覆盖率还不够连续。以下是一些在24点呈现的小写Arial'c'的参考图像:

没有抗锯齿的原始位图:





双线性过滤:





这里是在相同大小下呈现的相同字符带有库(stb):





最后,此处呈现为在OS X上呈现的样子(使用CoreText我认为):





我对stb库用于我的目的的任何方法都感到满意。 />

评论

最终的图像似乎正在使用亚像素渲染(请注意,左侧和右侧的彩色条纹是不同的颜色)。您是要使用这种方法(需要了解要渲染到的特定屏幕的像素几何形状)还是只需要最佳的像素渲染方法,而忽略子像素(可以在任何屏幕上显示)?

@trichoplax我想现在我对最好的像素渲染方法感到满意,而忽略了子像素(听起来更复杂)。一步一步来。 :)

这听起来像是一种好方法-我只想明确说明它,这样回答者就不会分散注意力来解释最后一张图片。

您能否在这种情况下解释双线性过滤的含义?我不明白该概念如何应用于字形形状的栅格化。另外,当您尝试“根据轮廓的像素覆盖率在边缘设置alpha值”时,您是如何实现的?超采样栅格化?

@NathanReed当然。对于双线性过滤,我扫过原始位图,然后为每个像素查看周围的三个像素(右边的一个,下面的一个以及对角线向右下方的一个)并将它们平均起来最终强度值。位图边缘以外的像素被视为0。

#1 楼

stb库的作者Sean Barrett写了一篇有关stb_truetype的栅格化工作方式的文章。这很容易理解。

本文介绍了两种抗锯齿方法,它们都是基于扫描线栅格化的。在扫描线栅格化中,您遍历像素的线(行),并跟踪字形轮廓的哪些边缘与扫描线相交(被视为数学零厚度线);那么您可以通过跟踪沿该线的输入/退出交点来识别轮廓内的像素中心。

您可以使用相交点的相对位置来计算部分像素覆盖率,从而进行水平抗锯齿到像素网格。例如,如果您在当前扫描线上的输入点为$ x = 4.6 $,则像素索引4将被设置为60%为空并且40%被覆盖。这听起来有点像您尝试执行的操作。但是,这对垂直抗锯齿没有帮助,因为扫描线仍被视为厚度为零的数学线。因此,本文建议仅沿垂直轴进行超采样:也就是说,处理在每个像素行内垂直隔开的多个“扫描线”,并将结果平均起来。

第二种方法是通过评估字形轮廓与每个像素正方形的相交区域,一次执行水平和垂直抗锯齿。它仍然基于扫描线栅格化,但是现在将扫描线视为一个1像素高的矩形,并跟踪接触该矩形的所有边缘。为了评估像素覆盖率,梯形规则用于计算每个字形边缘的正负号区域(取决于边缘的方向为正值还是负值),并将这些总和相加得出像素正方形内的总覆盖面积。 (本文涵盖了更多的实现细节,此外您还可以阅读源代码。)这比超级采样方法更快,更准确,但是实现起来比较困难。

最后,它是考虑渲染文本时是否要进行伽玛校正(与渲染其他任何东西一样)非常重要。从理论上讲,抗锯齿的coverage值不应直接用作像素值;它们应被视为Alpha,并用于背景颜色和文本颜色之间的线性颜色空间混合,然后转换为输出Gamma。但是,实际上几乎没有人这样做。我们习惯于看到非伽玛正确的文本,并且屏幕字体旨在通过这种方式呈现良好的外观。 (另一种说法是打印字体。)另一方面,如果由于任何原因使文本动画化,旋转或与像素网格不对齐,则伽玛校正将帮助其看起来更加一致,而无论其相对于像素网格的位置如何。

因此,是否应用伽玛校正的选择取决于个人喜好和应用需求。无论哪种方式,您都可能会看到诸如字体之类的伪影看起来变粗或变浅,具体取决于颜色和字体大小。

评论


$ \ begingroup $
太好了,谢谢!我已经看过stb_truetype的来源,但是我对计算机图形学的知识还不够全面,无法真正知道理论上正在发生的事情。但是我不知道他在上面发表的文章,所以这对我很有帮助,并且可以确定他使用的过程。我很高兴听到也许我在使用像素覆盖率方法方面做得正确,但我只是没有考虑垂直部分。 :)
$ \ endgroup $
–克里斯
16年8月1日,下午3:38

$ \ begingroup $
我只是问算法“抗锯齿”(或以某种方式改进)二进制1位图形和字体,有什么想法吗?
$ \ endgroup $
– uhoh
17年11月30日在6:21

#2 楼

这是抗锯齿的工作方式:

以四倍大小的大小在双水平渲染中渲染轮廓
取每个4×4块的平均值
将它们与正确的伽玛值混合前景和背景


评论


$ \ begingroup $
欢迎来到CGSE。问题不是关于抗锯齿的工作原理,而是关于使用/最适合字体渲染的技术。
$ \ endgroup $
–wychmaster♦
20 Jun 23'20:27