光栅化矢量图像的一般算法是什么?我发现了许多光栅化基元的算法,如直线,圆,贝塞尔曲线等。但一般情况下,我该怎么办?简单地说,在矢量图片中找到矢量图,得到它的像素并将它们放入光栅图像中?或其他什么?
另一个问题是,如何使用并发性来改善处理时间?例如,我可以分离矢量图并同时获取它们的像素。但也许有其他方法可以做到这一点?
答案 0 :(得分:4)
对于图像中的每个多边形,一般光栅化算法就是这样。
(多边形定义为由直线段和参数样条组成的一条或多条闭合曲线 - 在正常情况下,它们是二阶(圆锥别名二次)和三阶(三次)Bézier样条。这些闭合曲线是定义使得内部始终在左侧,随着曲线的移动;因此普通形状逆时针运行,孔顺时针运行。)
(i)(投影)将多边形转换为与目标位图相同的坐标系。分辨率不必相同,对于抗锯齿图像通常更大:例如,FreeType使用64像素。
(ii)(在Y中单调)必要时,将多边形的每个部分分成向上或向下连续延伸的较小部分。此阶段仅适用于弯曲段,使用Bézier样条时相对容易。通常的方法是反复平分,直到达到单调性。丢弃所有水平线段。
(iii)(标记运行限制)将每个段绘制成临时位图。使用Bresenham算法求直线;对于曲线,平分直到该线不超过(比如)真实曲线的1/8像素,然后从开始到结束使用直线。在绘制时,以某种方式标记像素以指示(a)它们是开始还是结束 - 向下线是开始,向上线是结束; (b)覆盖范围 - 形状内部像素的分数。这是算法在细节上的不同之处,以及区分缠绕规则(non-zero与even-odd)的位置。
(iv)(扫描)逐行遍历临时位图。对于每一行,从左到右扫描。通过(例如)将存储在位图中的数字添加到存储的数字来维持指示当前位置是否在形状内的状态。在简单的单色光栅化中,在前一阶段写入的这个数字在将边缘与形状交叉时为+1,在从形状出来时为-1。累计处于相同状态的像素运行。将运行发送到绘图模块:例如,FreeType会发出包含Y坐标,开始和结束X坐标以及0到255范围的运行。绘图模块可以将coverage用作应用于当前绘图颜色的Alpha值,或作为应用于纹理的蒙版。
以上是一个很大的过度简化,但提供了一般的想法。
大多数开源程序使用从以下项目之一派生的光栅化代码:
FreeType - 一个字体光栅化器,包含单声道和抗锯齿光栅化器模块,这些模块相对容易单独使用 - 也就是说,对于任何形状,不仅仅是字体。我已经在几个商业便携式C ++项目中成功使用了这个系统。
FreeType的系统灵感来自Raph Levien的Libart。
Anti-Grain是另一个受欢迎且颇具影响力的C ++库。
还有Kiia Kallio实施的scan-line edge flag system,看起来很有希望,似乎比抗粮更快。
大多数但不是所有这些库都接受由二次和三次Bézier样条曲线以及直线段构成的形状。那些没有的(例如,K。Kallio的图书馆)只采用直边多边形;但很容易将曲线“展平”成一系列线段,这些线段比实际曲线所需的最大距离更近。 FreeType在内部执行此操作,并且可以在必要时借用其代码。