CnGraphics快速图像处理库_第1页
CnGraphics快速图像处理库_第2页
CnGraphics快速图像处理库_第3页
CnGraphics快速图像处理库_第4页
CnGraphics快速图像处理库_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、CnGraphics快速图像处理库设计说明作者:与月共舞()2002.03一、综述CnGraphics.pas单元实现界面类的快速图像处理基础库,核心部分是一个使用24BitRGB格式的TCnBitmap位图类,以取代Delphi自带的TBitmap,大量的扩充包括快速访问象素、抗锯齿位图缩放、旋转、抗锯齿图形绘制、快速AlphaBlend、渐变色绘制、平滑字体绘制、各种滤镜特效等,当前的代码量为6500行。与界面类的设计目标一致,图像库设计的重点也是对速度和资源占用的优化。1、为什么要设计一个快速图像处理库?Delphi在Graphics单元中定义了一个相当优秀的图形图像库体系结构,它将复杂

2、的Win32GDIAPI封装为相对简单的使用方式,但不足处是底层访问和高级应用的功能不够。在图像处理的大量象素级访问中,使用TCanvas.Pixels简直就是一场噩梦。当然用TBitmap.ScanLine会是一个好的选择,但对于一个追求个性化界面的组件包来说,仅靠TBitmap提供的那些来自操作系统的图像功能是远远不够的。为了实现最大的代码重用和高效率开发,我们需要一套底层的快速图像处理库来提供对各种界面效果设计的支持。2、通过使用图像处理库我能做什么?相对于Delphi提供的图像处理功能,CnGraphics的设计重在速度快、功能强。它以FastLib为基础,提供了快速的底层数据访问支持

3、和大量的通用算法,主功能有:通过Pixels和ScanLine属性,可以直接访问位图中的图像数据,速度相当快。象素数据以一个点RGB三个字节的方式存放,可以非常方便地进行处理。使用TCnBitmap的各种外部接口方法,方便地与VCL其它图像类以及文件、流交换数据。通过TCnBitmap提供的图像绘制、缩放、平铺、旋转等方法快速绘制图像,Canvas属性则允许用户按VCL方式操作位图。TCnBitmap支持抗锯齿图形绘制功能,使用二次插值算法进行几何图形绘制。快速的AlphaBlend混合、完整的透明支持、渐变色(多种颜色多种方式渐变)绘制、平滑字体显示为个性化的界面提供强劲的支持。相当方便地调

4、整整个图像的RGB颜色分量、对比度、亮度、饱和度、灰度化、彩色化、颜色替换,对图像进行几何翻转、平移、变换等。模糊、锐化、噪声、去噪、马赛克、喷溅、浮雕、旋涡等滤镜处理方法提供接近专业图像软件的效果,还可自定义滤镜处理算子。附加的与图像处理相关的运行时间库如HSL、RGB颜色变换等。3、怎样使用图像处理库?CnGraphics提供了较多的功能,但在使用上相对还是比较简单的。图像类封装了大部分底层的功能,调用者一般不需要知道具体实现细节,公开的属性和方法尽量使用通用的命名习惯和标准,只有一些细节部分需要调用者注意。除了TCnBitmap,图像库还提供了其它一些类如TCnGradientColor

5、、TCnFont等,它们主要针对控件编写进行设计,用作控件属性时对编写者透明,操作方式也尽量为方便使用而设计。核心设计这一部分内容主要针对有经验的开发人员编写,介绍图像处理库的核心设计内容,涉及很多实现细节方面的东西,很多内容并未定型,普通用户可以跳过该部分。当然在有图像处理经验的程序员眼里,这部分内容可能极简陋甚至漏洞百出,如果有错误还请谅解和指正。CnGraphics单元在设计中大量参考了FastLib、Graphic32、FlatStyle、pnBitmap等图像包的设计:1、位图格式。常用的彩色位图格式有8位、16(15)位、24位、32位等。使用调色板的位图固然有其优势,但在硬件资源

6、发展到今天这个地步后,基于索引色的方式再不能满足视觉效果的要求,CnGraphics中彻底抛弃了调色板,所有与调色板相关的处理全部转换由VCL或操作系统处理。16位格式在游戏开发中曾相当流行,也有很多优秀成熟的引擎和算法,不过操作起来似乎不太方便,未做选择。24位格式一个象素占用三个字节存放,使用方便,是最常用的格式了,缺点是象素数据未按4字节对齐,不方便并行处理优化。32位的图像在RGB之外增加了Alpha不透明度字节,从底层上支持类似PhotoShop中图层和蒙板的功能,象素数据按4字节对齐存放,可以方便地使用MMX指令进行加速,同时这种格式得到了Win2000的底层支持。缺点是占用空间较

7、多、算法较复杂,象素级的Alpha支持在控件中用处好象不大。在选择24位RGB格式还是32位RGBA格式中,考虑了很久还是决定用24位格式,但不排除将来升级到32位格式的可能。2 、类层次结构。TCnBitmap派生自在CnClasses中定义的TCnThreadPersistent类,继承了通知事件、更新计数和线程安全等功能。之所以没有设计为从TGraphic或类似类中派生,原因是TCnBitmap在整个架构中是相对独立的,它并没有增加新的图像格式,与VCL的数据交互可通过接口方法实现,而它主要是为CnPack界面类设计,当然不排除以后修改的可能。快速图像库中仅考虑24位格式的Bitmap位

8、图,JPEG、GIF、PSD、PND等其它格式的图像文件支持,VCL预留有相当合理的接口,已有很多免费的第三方实现代码,通过TPicuture就可以相当方便地访问。如果CnPack中要提供对它们的支持,也可直接在VCL这一级上实现。TCnBitmap目前的结构设计没有考虑太多供派生子类重载的内容,主要是因为它既实现了底层的操作又提供了大量可直接使用的应用层方法,如果要进行功能扩充可直接在类中修改实现,另外执行速度和编译代码长度的考虑也是一方面内容。3 、GDI资源分配和管理。在Win9X中,系统资源占用一直是让很多程序员头疼的问题,在FastLib、Graphic32、pnBitmap等包中,

9、每一个位图对象实例都将消耗一个位图句柄HBITMAP、一个内存DC共两个GDI句柄资源,如果大量使用,将占用相当多的系统资源。实测在Win98SE下,100个位图句柄将消耗约8%的GDI资源。被很多人推崇备至的ExtraPack对GDI资源的消耗也是惊人的:在小弟的机器上(PIII800,PWin98SE),它的Demo运行后,系统GDI资源马上由91%降到了48%,再运行一个实例系统立即提示“资源不足”。当控件无法获取DC进行绘制时,Dephi程序将弹出“Canvasdoesnotallowredraw”错误,而设计期则可能出现“参数错误”。在界面类设计中,TCnBitmap是控件界面绘制的

10、核心,如果对资源占用不加控制,将导致严重的后果。在TCnBitmap里,可自动管理的资源包括:DC、位图句柄。从Delphi的Graphics单元可知,Delphi在DC使用上极为谨慎,内存DC(主要是TBitmap的Canvas句柄)用过立即释放,单个程序所有窗口控件最大只允许同时获取4个DC(保留了Win16下的限制)。TCnBitmap使用线程安全列表与定时器来释放内存DC(Delphi是在窗口控件主消息循环过程中释放),所有内存DC只要没有加锁,都将之释放。HBITMAP位图句柄在Delphi中是长期保留的,而TCnBitmap也将它设计为动态释放,由于不使用调色板,从内存数据块创建位

11、图是相当简单的,将位图数据备份释放位图资源也相当快。这种转换在TCnBitmap中透明实现,不管当前是否已分配位图句柄,都不影响图像处理功能调用,当访问Handle、DC或Canvas属性时,对象会自动分配相应句柄并进行数据切换,而Pixels、ScanLine、Width等属性始终指示位图的实际内容,各种图像绘制、滤镜方法也同样可在任何时候使用。事实上,如果不访问DC、Canvas等属性,TCnBitmap对象实例可以在不分配任何GDI句柄下使用几乎全部的图像处理功能。通过对位图资源进行自动管理,可以使程序在后台运行时只占用尽量少的GDI资源。为了满足不同的需要,TCnBitmap设计了一个

12、属性GdiAllocStyle将位图分为三种:内部位图、普通位图和外部位图。获取和释放一个DC花费极少的时间,故所有模式下DC都是即时释放的。内部位图主要用于内部绘制,位图句柄用后立即释放。普通位图的位图句柄定时释放。外部位图用于频繁与DC打交道的场合,位图句柄分配后长期保留。具体管理方式仍未决定,最终将根据运行速度、测试结果进行调整。自动资源管理功能对调用者来说是透明的,除了一些特殊情况,编写代码时可以不用考虑。4 、象素级数据访问。实际的位图数据存储在内存块中,不管是否已分配位图句柄,Bits属性始终指向实际位图数据,长度为Size。Width和Height属性定义位图大小。位图数据块按扫

13、描线存储,每行字节数按4对齐,每行占RowInc(保护属性)字节空间,而Gap(保护属性)等于RowInc-Height*3,在图像遍历中使用。为了快速取得扫描线起始地址,定义了扫描线数组FScanLine,在内部使用时可以实现用一条汇编指令取得扫描线地址,二条指令取指定象素地址这样的访问速度。公开的Pixels和ScanLine属性增加了范围判断,访问速度稍有下降,如果要访问大量象素,推荐使用ScanLine。另外,PixelsF属性支持小数坐标的象素访问,使用二次插值算法(见后),速度较慢。5 、Canvas属性与外部数据接口。为了兼容VCL图像处理方式和重用VCL的代码,TCnBitma

14、p中仍然保留了Canvas属性。Canvas提供Font、Brush、Pen等GDI对象的封装类,VCL的Graphics单元中已经使用了非常高效的方式(基于引用计数)管理这些对象,而大部分Win32GDIAPI也在TCanvas中有相应封装,TCnBitmap通过提供Canvas属性重用这部分代码。同时还提供了一些扩充的GDI功能,如抗锯齿的图形绘制、平滑字体绘制功能等。Canvas申明为TCnCanvas。TCnCanvas从TCanvas中派生,重载CreateHandle方法创建内存DC,有一点需要注意的是,TCnCanvas的Handle属性重申明为只读属性,请不要更改它。一般说来,

15、如果方便,调用者应该尽量使用TCnBitmap提供的图形图像方法,避免使用Canvas属性以减少资源开销。在设计独立结构的图像处理库的同时,仍然考虑了与外部数据的良好接口。TCnBitmap提供了三种方式与VCL和外部数据进行交换:Assign方法可直接将VCL中的TBitmap、TGraphic、TPicture以及它们的派生类中的图像数据导入,而AssignTo方法(保护方法)则允许通过类似Bitmap.Assign(CnBitmap)的调用将数据导出。LoadFromFile、LoadFromStream、LoadFromResourceID等方法可直接从文件、流、资源中装载图像。其中L

16、oadFromFile方法内部使用了TPicture的LoadFromFile方法,支持从Icon、Jpeg等多种格式文件中装载图像,可直接与TOpenPictureDialog搭配使用。Draw、StretchDraw等图像绘制方法也可以引入TGraphic、DC中的图像,而DrawTo等后缀为To的绘制方法则允许将图像绘制到DC等外部容器。6 、代码优化方式。作为界面类的核心,图像处理库的运行效率直接影响到最终作品的性能。TCnBitmap中相当部分的设计和算法从FastLib、Graphic32这两个免费图像包中修改移植而来。FastLib支持8位和24位格式,Graphic32支持32

17、位格式,前者提供大量的快速图像处理算法,后者结构严谨、规范又不失高效。在图像处理库中,代码运行速度的优化主要分为三个层次:算法级、代码级、CPU级,三个层次互相渗透。一般的优化方式主要有两大类:尽量短的一次操作时间和尽量多的一次操作数据量。为了使执行一次操作的平均时间缩短,可以用执行速度快的指令取代较慢的指令,减少最内层循环的操作步骤,减少重复运算等方法实现;为了在一次操作中运算多个数据,可以使用双字并行运算、MMX指令等方法成倍提高处理速度。TCnBitmap目前的速度优化方法主要来源于FastLib库,特点是大量的运用查表法、加减移位代替乘除、整数运算代替小数运算等方法,属于第一类优化方式

18、。查表法在FastLib中得到了广泛的应用,主思路是使用在堆栈中分配局部数组存储临时表格以减少重复的运算,用速度极快的MOV指令取代运算指令。这一方法在固定值Alpha混合、位图属性调整等很多代码中使用,大大提高了运行速度,最有代表性的代码是图像灰度化(Grayscale方法)中,div3这样的运算也使用了加法运算加查表法来代替,因为在CPU这一级,div的运算速度比加法慢了近一个数量级。加减移位代替乘除运算比较简单,shr2的执行效率远高于div4。而在循环中,使用累加来取代乘法运算的例子随处可见。不过使用移位要注意的是:一般不要对负数进行运算以及范围检查选项应该关闭($R-)。这里多说几句

19、,事实上,Delphi的后端编译器极其优秀,类似这样的代码a:=adiv16(a为无符号数),编译后的指令可能会是shrax,4这样的形式。使用整数运算取代浮点数运算的代码可能比较难看懂,原理也很简单:一般说来,我们需要处理的数据不会超过16位,为了充分利用32位处理器的运算能力,将低16位(当然也可以是8位或其它位数,视精度需要,有时考虑符号位,使用15位)作为小数来使用。数据运算前全部左移16位,运算最终结果再右移16位输出。通过这样的处理,速度比浮点运算加取整处理可以提高二到四倍甚至更高。第二类并行运算方式在Graphic32图像包中有大量应用,基于TCnBitmap采用24位格式这一特

20、点暂无太多应用。而CPU级如并行指令执行、分支预测、寄存器阻塞、高速缓存、MMX、3DNow!、SSE指令加速等方面因素的优化暂时还没有能力考虑:)在TCnBitmap的一些可能会频繁使用的代码中,经常通过增加代码长度来缩短执行时间,如图像绘制中的透明处理等。同样,核心代码的优化对调用者也是透明的,随着后继优化的进行,整个界面类的执行效率将不断提高。7 、抗锯齿处理与二次线性插值。抗锯齿处理是图像库重点考虑的功能,包括缩放、旋转等几何变换、几何图形绘制、字体显示等部分。SmoothFilter属性决定了缩放、旋转等方法是否使用二次插值算法。在数字图像变换中,当一个目标象素映射为原位图的非整数位

21、置时,必须使用一种方法确定最终颜色值,即插值方法。最简单的是最近邻插值算法(或零阶插值),使用最近象素的颜色值来代替。二次线性插值算法(或一阶插值、双线性插值)使用二次线性函数来拟合原图像四个顶点:f(x,y)=ax+bx+cxy+d假设原位图局部数据如下:f(0,0)f(0,1)f(x,y)f(1,0)f(1,1)f(x,y)这里指的是位置为非整数的图像某象素的灰度值(或RGB颜色分量),而f(0,0)等为整数位置的相邻四个顶点的灰度值,0<=(x和y)<=1O通过一系列推导(过程略),最终可得到下面的式子:f(x,y)=p(0,0)f(0,0)+p(0,1)f(0,1)+p(1

22、,0)f(1,0)+p(1,1)f(1,1)p(0,0)=(1-y)(1-x)=(1-y)-p(0,1)p(1,0)=x(1-y)p(0,1)=y(1-x)=y-p(1,1)p(1,1)=xy在这种方式中,使用了六次乘法六次加法,原因是计算出四个加权值可以对RGB三个分量分别运算,比较方便且总体速度较快。使用其它运算公式还可以减少运算次数,有兴趣的朋友请自已查阅相关资料。二次插值的缺点是固有的平滑作用会使图像细节退化,使用高阶插值对更多的象素进行运算能得到更高质量的图像,但运算量太大,算法复杂。Graphic32中提供了一种三次插值算法,有兴趣的朋友可以研究。当然,TCnBitmap以后也可能

23、提供类似的算法。TCnBitmap的缩放、旋转、图形绘制使用了上面的插值算法,同时还使用了代码优化中的一些算法,希望这份文档可以帮助阅读者较好地读懂代码(想想小弟阅读几乎没有任何注释的FastLib代码时的情形吧)。在平滑字体绘制中,使用了相对不同的处理方式。基本思路是将文本放大数倍后再用均值算法缩小以产生抗锯齿的平滑效果。具体实现中,使用了一个灰度位图来保存平滑处理后的文本图像,再以此为蒙板,将灰度值做为Alpha不透明度把字体前景与背景相混合,前景可以是单色、渐变色、纹理或任意的位图,以实现特效处理。而对灰度位图进行处理比如模糊、边缘检测等还可以实现其它的字体形状特效。8 、图像透明、Al

24、pha混合与渐变色绘制。这里的透明指的是绘制图像时仅绘制前景而忽略背景,前背景的区分可通过定义背景色和使用掩码图两种方式,定义背景色相对简单而被大量应用,而在Windows中图标光标好象是使用掩码图方式存储的。TCnBitmap采用第一种方式,用Transparent和TransparentColor属性来决定是否允许透明和透明色,当透明色为缺省值clDefault时,实际透明色定义为图像左下角象素颜色值(与TBitmap保持一致)。绘制透明位图最直观的方法是逐点判断颜色值和透明色来决定是否绘制,但由于一般的象素级访问速度太慢,很多书上提到的算法都采用掩码图加使用特殊位运算的Bitblt位块传

25、输方法来实现。VCL和很多第三方代码中使用后者,但在TCnBitmap中,由于象素级访问速度已不是问题,而操作系统提供的Bitblt需要DC支持,故使用了第一种较“笨”的方法来实现。同时,使用这种方式,在图像绘制二次插值时可以根据四个顶点是否透明而改用目标象素值代替,以实现较好的绘制效果。TCnBitmap中大部分图像绘制算法均支持透明处理。Alpha混合(Blend)在图像处理和游戏中大量应用,即通过对多幅画面按一定比例进行混合以实现半透明效果,AlphaBlendValue又叫不透明度。在Win2000中,窗口的不透明度由操作系统底层支持,D6中的窗体新增了两个属性可以简单地设置这一功能(

26、调用API)。而界面类将在控件这一级实现不透明度属性,详见CnVCLBase界面组件基本类。TCnBitmap中通过自己的代码实现固定数值的Alpha混合,使用查表法进行优化,另外还支持Alpha线性渐变的混合方式。渐变色也是常用的图像特效,CnGraphics中使用TCnGradientColor来定义渐变内容,它派生自TCnPersistent,可直接用于控件的发布属性中。渐变内容分为渐变色带和渐变方式,除了起始色和结束色,还可以定义任意多的中间色(通过TCnMiddleColor实现),渐变方式则规定了绘制方法。当把渐变色用于组件属性时,对编写者完全透明,最终组件中将包含一个渐变对话框,可在运行期使用,还可用于渐变类属性编辑器在设计期使用。(在Delphi5/6中,TOwnedCollection派生类只有当Owner为T

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论