随笔-341  评论-2670  文章-0  trackbacks-0
    前天在博客上说希望开发一个尽量独立于GDI的图形库。这个图形库将不使用其他图形库例如GDI+、OpenGL以及DirectX等。图形库使用GDI的原因如下:
    1:字体的边框比较难获得。直接读TTF文件暂时还不想做,因此想借助GDI的API获取文字的Bezier轮廓。
    2:不使用GDI无法把图片刷上窗口。
    因此这个图形库使用的GDI的功能也仅限于此。当然,开发出来的结果必然是GDI所不能达到的。GDI+的结构也稍微有一点点不理想。

    为什么GDI和GDI+的速度都不太理想呢?下面的分析将会给出一个可能的解释。

    今天早上考了软件配置管理,也就是让我们了解一下为什么需要Subversion这样的软件来帮助我们开发软件。考完试回来的路上就构思了这个图形库的结构。让我们考虑一下图形库所需的功能,也就是需求分析了。我们用惯的图形库都有绘制图形、文字以及图像的功能。图形有画刷和边框,其中边框是具有形状的。

    首先考虑一下文字。我们知道现在绝大多数的文字都是由Bezier边框构成的,虽然这种图形是镶嵌图形(也就是有孔),不过孔不是什么大问题。我们拿到了文字的Bezier边框之后,就可以将文字转换为几何图形了。于是实际上只需要绘制图形和图像就够了,外加一个获取边框的程序

    其次,绘制图像实际上也是使用一个跟边框有关系的画刷去绘制一个矩形而已。所以,绘制图像的时候,我们需要创建一个几何图形以及相匹配的设置的画刷

    再者,让我们考虑以下图形。我们知道,图形由边框和内部构成,这两个部分都是可选的。边框有填充物、有线条类型(实线虚线等)、有线条的边界形状以及宽度等设置。那么,图形的边框通过这些设置就可以转化为一个或多个几何形状和填充物。于是,我们只需要一个将边框转换为几何图形的程序就可以将边框也去掉了,剩下的就是使用画刷填充几何图形。

    那么,几何图形就是由直线、弧线、Bezier曲线以及其他线条方程组成了。这个就跟架构无关了,只需要解决相应的数学问题就行了。剩下的就是画刷的问题。我们知道画刷有若干类型,譬如单调颜色、渐变以及图像等。渐变分两种,一种是跟绘制的几何图形有关的,另一种是跟绘制的几何图形无关的。于是我们在使用跟绘制的几何图形有关的画刷的时候,我们可以创建一个根据某种几何图形渐变的画刷,并且让这个几何图形跟被绘制的几何图形相同,从而可以去掉『跟绘制的几何图形有关的画刷』了。

    于是画刷就只有一种属性了,也就是通过坐标来获取颜色。因为这个时候画刷已经跟被绘制的几何图形无关了。于是到了这里,我们很容易联想到多态。使用一个接口包含『坐标返回颜色』的函数,就可以填充几何图形了。但是这样做是不好的,因为一个几何图形有成千上万个点,调用这么多次虚函数是会严重影响效率的。所以填充几何图形这种工作应该完全由画刷负责。那么我们如何多态呢?实际上可以这样。我们定义一个接口,给出几何图形然后绘制。然后继承一个类出来,这个类是模板类。模板类传入一个参数用于决定如何通过坐标返回颜色。因为画刷跟被绘制的几何图形无关,所以可以这么做。这个时候,我们就可以把填充跟获取颜色分开了,但是编译的时候仍然会让他们结合在一起。所以无论几何图形有多大,调用的虚函数也就是一次。

    好了,到了这里,一个图形库实际上就是由通过一定模式填充几何图形的函数,加上构造几何图形以及画刷的各种各样功能强大的周边函数组成。

    那么考虑到这里,我们如何根据一个点获取颜色呢?单调颜色非常好处理,无论如何都返回这个颜色。渐变的话,根据复杂的几何图形渐变仍需考虑一下好用的算法,根据直线、方框以及椭圆等凸多边形渐变实际上是相当简单的。剩下的就是根据图像来获取颜色了。根据图像获取颜色有几个需要考虑的问题。第一个是超出图像的部分如何处理,这个比较好办,要么就返回一个颜色,要么就不填充,要么就让图像堆砌起来。第二个问题就是根据被绘制的点经过变换到图像上的点的时候,这个点可能不是整数。这个时候我们可以寻找临近的点的颜色,或者根据缩放尺度来计算若干点的颜色的加权平均值。当然第二种是比较逼真同时也比较慢的。

    剩下的一个问题就是反锯齿效果了。这个不用过多解释,实际上也有非常多的办法来解决,在框架没有定下来之前讨论这个是没有意义的。因为图形库实际上是支持Alpha通道的,所以并没有什么技术上过于困难的地方。

    图形我们就完全解决了,现在开始图像的问题。我们仍然可以通过修改通过点获取颜色的程序来实现调整一个图像的对比度啊、亮度啊、甚至执行一些模糊锐化边缘化等处理。我们甚至可以借用OpenGL的Color Matrix这种概念来执行一些比较简单的线性颜色变换。这些效果实际上只需要慢慢添加进去就可以了,不过如何将多态的损耗减至最小仍然需要考虑。

    如果以上的讨论所涉及到的问题全部解决的话,我们可以得到一个跟GDI+一样,甚至是更加强大的图形库。好了,现在讨论一下为什么GDI和GDI+的速度都比较慢。我们可能经常会重复绘制一些没有任何变化的、具有复杂画笔的几何图形。通过画笔构造边框的轮廓是一件复杂的工作,我们使用GDI和GDI+就会在每一次绘制的时候重复计算这些东西了。不过由于GDI和GDI+的接口过于友好,我们无法干预这件事情。所以效率下降就是必然的了。而且绘制文字等价于填充几何图形,因此也是如此。GDI+唯一一个比较快的就是图像处理了,因为它的图像处理并不是通过本文讲述的转嫁到画刷的办法来实现的。当然,如何打开和保存各种格式的图片文件的事情就暂缓处理了,这根图形库本身是无关的。至于到时候这个图形库所展现出来的接口是如何的?我想仍然会有画笔啊画刷啊这种概念的,只不过会复杂一点,为了解决上面所说的问题也会繁琐一点。

    图形库,仅仅是数学问题而已。
posted on 2008-06-10 19:13 陈梓瀚(vczh) 阅读(4370) 评论(13)  编辑 收藏 引用 所属分类: 其他

评论:
# re: 图形库的概要设计 2008-06-10 20:57 | 空明流转
图形库,仅仅是数学问题而已。
---------这句话很赞同。很明显我在思路上不如你清晰。  回复  更多评论
  
# re: 图形库的概要设计 2008-06-10 23:16 | Touchsoft
图形库,仅仅是数学问题而已。
我最近为了图形,不得不学习数学了 :)  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 00:26 | 陈梓瀚(vczh)
楼上做的是……?  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 01:03 | Touchsoft
乱做呢,就学习3D方面的,数学在这方面用的蛮多。  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 01:55 | 看你是头脑发昏
去研究一下AGG,别一头脑发昏就长篇大论  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 02:12 | 看你是头脑发昏
所谓的二维图形运算实质上都是用CPU进行矢量的光栅化运算,别以为M$设计GDI+的人是白痴,你还能设计出比GDIPlus更快更强大?

看你这所谓分析实际上你完全就不了解2D图形学,你那个所谓的模板思想,去查查AGG多少年前就出来了?AGG功能强大没错,但是它有性能优势吗?

近年来兴起OpenVG这样的2D图形接口,如果不借助硬加速,照样完全没有性能优势!

数学问题?博主你甚至连二维图形学具体涉及哪些算法都没搞清楚。给你个忠告,做学问就踏实一些,别动不动就指点江山,简直贻笑大方。
  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 02:42 | foxtail
@看你是头脑发昏
他也是自己思考过的,很不错了。  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 04:03 | Kaja
喜欢攻击人的人可能需要去心理咨询  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 04:08 | 知道你很牛
@看你是头脑发昏
被你贻笑大方,那你又被谁贻笑大方阿?
张嘴闭嘴都是别人设计的库,你又拿出什么杀手锏了没?靠,最讨厌就是你这种人,真正的没多少本事,指手画脚到很在行。

要是你真牛逼,就拿出你的真本事来,让大家对你顶礼膜拜。  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 07:33 | 陈梓瀚(vczh)
呃呃,多谢楼上三位兄弟替我说话。还是不要在我的地盘上大家的好。不过『看你是头脑发昏』兄弟,胡乱猜测别人的水平是不好的。

如果你有更好的见解请拿出来,知道点什么更先进的东西也行,指出我的设计的缺点也行,不要跟混混一样光留下这么点话就走。而且,如果真的想只留下这么点话的话,麻烦留下联系方式或者你自己的blog,方便日后讨教。  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 12:20 | 看你是头脑发昏
看来这位小朋友非常之不谦虚经不得人说以外,甚至没有论坛掐架的经验。

要先进的东西吗?去研究一下如何实现2D硬加速,不要用软加速的扫描线算法,除了重复造个轮子之外没有任何意义,或许,连个轮子都造不圆。

看不出你上门那篇文章除了自以为是GDIPLUS不行以外,还有任何技术含量,跟你谈设计不是扯谈?

需要猜测你的水平么?这不明摆着的事,扪心自问你的2D图形学水平有多少斤两再出来胡说。

小朋友,你要是用马甲帮自己说话的话,最好把时间隔长些,别在几分钟之内,这种行为很幼稚,别又要让人说你贻笑大方哟~  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 21:34 | Kaja
小朋友,你要是用马甲帮自己说话的话,最好把时间隔长些,别在几分钟之内,这种行为很幼稚,别又要让人说你贻笑大方哟

555可悲可悲啊。。。以小人之心度君子之腹还自以为得意,看来Ls真的老混昏了!嗤嗤嗤,强烈鄙视之!这种人当他透明好了  回复  更多评论
  
# re: 图形库的概要设计 2008-06-11 23:41 | 陈梓瀚(vczh)
禁止互相吵架,本帖想继续吵请注册帐号。省得被无中生有说用马甲。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理