在计算机图形学中产生图形锯齿是因为计算机屏幕中的点是离散的有大小的像素点来表示的,当我们用计算机画连续的曲线的时候由于屏幕像素没有办法表示小数坐标,然我们用四舍五入后整数来表示,那么我们就会出现锯齿。
计算机图形学是一门想方设法欺骗你眼睛的学科,要达到消除锯齿感可以有两种方式来抗锯齿,一种是次像素填充,目前很多矢量字都采用这种方式,填充的不再是像素而是针对像素的R,G,B分量,用放大镜看我们的屏幕就可以发现我们的屏幕最小单位是颜色分量不是像素,这就是所谓的次像素,那么它消除锯齿的原理是增加点的个数,即增加分辨率,但这种做法不足之处是边缘会出现彩色的偏色,以及不同的LCD由于设备原因会导致不同的效果。一般这种做饭多用于文字,因为文字的笔画多,相对密,相比较用透明度来消除锯齿,这种方法要更好。
但以后再谈基于透明度抗锯齿的文字绘制以及优化。
第二种方法就是今天我们要介绍的半透明的抗锯齿。其实很简单,就是由高分辨缩小到低分辨率,然后在边缘通过颜色混合来计算最后的颜色值。
在一般的矢量图形库中,比如我们要画个倾斜直线,那么实际上在raster的时候会把这个扩大到4倍,有的甚至更多,越大越好,一般是4倍。
在这个4倍的直线画布中我按照正常的四舍五入的方式在画布上设置点,画好,因为屏幕的分辨率提高了,所以抗锯齿的效果会好,人的眼睛也会觉得平滑,然后在缩放回正常的分辨率,那么实际就是横向来做一次运算,竖向做一次运算,然后得到颜色值,为新的颜色值。那么在锯齿边缘就会出现alpha混合过的像素。
比如像素模板 R以及横向和竖向的权重
static UI8 AntialiasingWeightX[]={1,1,1,1}; // 这里可以根据不同的应用场合来改变,这里暂取平均
static UI8 AntialiasingWeightXTotal=4; // 所有值的和
static UI8 AntialiasingWeightY[]={1,1,1,1};
static UI8 AntialiasingWeightYTotal=4;
R11,R12,R13,R14, (R11*weightx+R12*weightx+R13*weightx+R14*weightx)/weightTotalx;
R21,R22,R23,R24, (R21*weightx+R22*weightx+R23*weightx+R24*weightx)/weightTotalx;
R31,R32,R33,R34, (R31*weightx+R32*weightx+R33*weightx+R34*weightx)/weightTotalx;
R41,R42,R43,R44, (R41*weightx+R42*weightx+R43*weightx+R44*weightx)/weightTotalx;
这样就可以得到竖直方向上的R1,R2,R3,R4然后在用上面的方法是用权重Y来求出最后的像素
(R1*weighty+R2*weighty+R3*weighty+R4*weighty)/AntialiasingWeightYTotal
试想下当我们是个斜线的时候比如像右下角倾斜的字先,那么左边还有上面的半透明出来的颜色值,那么也可以消除锯齿。
而矢量图形库值得优化的地方就在与,尽可能的减少计算抗锯齿的像素,因为计算代价太大。
比如实心填充,完全不用理会中间的,中间的就直接写颜色,而只对边缘用半透明抗拒次。
我自己目前写的矢量图形模块的效率就比较低,因为就是对多有的像素做这样的处理,大概要100 ms才能画出两个椭圆图形。
所以以后还要优化,但目前我不做优化的原因是我还没有写完flash player的矢量图形库的一些基本要完成的点,避免过早的优化。
等我写完后会开源出来。
另外还要说一点,谁想学矢量图形库,最好看看flash player 的概念。
最好是解析播放简单的swf文件,这样你就可以直接通过micmedia 的flash制作工具制作出矢量图形然后你画出来,这样可以大大的提高开发效率,对于用来做界面的同学,可以把micmedia作为一个界面编辑器,最后你解析swf,导出自己的界面布局,是不是很酷!
欢迎喜欢flash 矢量图形的同学一起来交流