开篇:润墨网以专业的文秘视角,为您筛选了一篇C#环境下GDI+绘图效率研究范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!
[摘要]本文在简单介绍GDI和gdi+的基础上,指出GDI+在绘制动画时效率不足的劣势,并对三种不同的GDI+动画绘图方式进行了详细的阐述;最后实现了一个GDI+界面绘图程序,比较和验证了三种不同方式的绘图性能。实验表明,使用双缓冲和bitblt结合的方式,可以有效的解决直接绘制方式的闪烁问题,提高绘图效率。
[关键词]GDI+;动态绘图;双缓冲;bitblt
中图分类号:P631.84 文献标识码:A 文章编号:1009-914X(2015)05-0134-01
1.引言
GDI是微软公司的著名的二维图形引擎,GDI+则是微软公司为了提高显示效果而推出的一种新型图形引擎。GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。
GDI+是Windows XP中的一个子系统,它主要负责在显示屏幕和打印设备输出有关信息,它是一组通过C++类实现的应用程序编程接口。顾名思义,GDI+是以前版本GDI的继承者,出于兼容性考虑,Windows XP仍然支持以前版本的GDI,但是在开发新应用程序的时候,开发人员为了满足图形输出需要应该使用GDI+,因为GDI+对以前的Windows版本中GDI进行了优化,并添加了许多新的功能。
作为图形设备接口的GDI+使得应用程序开发人员在输出屏幕和打印机信息的时候无需考虑具体显示设备的细节,他们只需调用GDI+库输出的类的一些方法即可完成图形操作,真正的绘图工作由这些方法交给特定的设备驱动程序来完成,GDI+使得图形硬件和应用程序相互隔离.从而使开发人员编写设备无关的应用程序变得非常容易。Microsoft Windows GDI+服务分为以下3个主要部分:
(1)二维矢量图形。矢量图形由图元组成,而图元则由一系列坐标系统的点集组成。例如,一条直线可以由它的两个端点所确定,一个矩形可以通过给出它的左上角点的位置加上它的宽度、高度来确定。一个简单的路径可以由一个由直线连接而成的点数组来描述。一条贝塞尔样条是由4个控制点所描述。
(2)图象。某些图片很难或者不可能采用矢量图形技术来显示。比如,工具栏按钮图片和图标和一张拥挤的棒球馆的高分辨率的数码照片。这种类型的图像采用位图进行存储,即由表示屏幕上独立点的颜色的数字型数组所组成。用于存储位图信息的数据结构往往比矢量图形要复杂的多,因此出于此种原因GDI+中提供了好几种类,如Bitmap类。
(3)排版。排版关系到多种字体、尺寸和样式文字的显示。GDI+提供对这项复杂的任务给人深刻印象的的支持。新的特性中包括了子象素抗锯齿功能,它使得在液晶显示屏上可以显示更加平滑的显示文本。
2.GDI+绘图方式简介
下面对Microsoft Visual Studio 2010编程环境下基于c#编程语言的GDI+的几种不同的绘图方式进行简介。在Ctt中,GDI+图形图像处理用到的主要命名空间是Systenl.Drawing,它提供了对GDI+基本图形功能的访问,主要有Graphics类、Bitmap类、从Brush类继承的类、Font类、Icon类、Image类、Pen类、Color类等。C#中GDI+绘图的方式主要分为直接绘制,双缓冲和使用GDI函数三种。以绘制一个矩形为例,无论采用哪一种方法,都需要先在当前窗口先创建画板、矩形和画刷:
Graphics g=this.CreateGraphics();∥在当前窗口创建一个画板
∥定义矩形,参数为起点横纵坐标以及其长和宽
Rectangle rect=new Rectangle(10,10,200,200);
∥单色填充
SolidBrush b1=new SolidBrush(Color.Blue);∥定义蓝色画刷
如果使用直接绘制的方法,则只需要调用FillRectangle函数用画刷直接填充矩形即可:
g.FillRectangle(b1,rect);∥填充这个矩形
这种方法比较简单易用,容易理解,在绘制静态图形时,能够很好的满绘图需求。但是在绘制动画时,不仅效率低下,而且会产生图片闪烁的现象。其原因是GDI+画图是将所有的图元先存入显卡的缓存,显卡会每隔一段时间将显存中的内容输出到显示器中。每画一个图元,系统就要做一次图形的绘制操作。图形的重绘是很占用资源的,特别当需要重绘的图形数量很多的时候,所造成的消耗就特别大,导致闪烁,不流畅等情况。
使用双缓冲的绘图方式可以有效的消除闪烁的现象。双缓冲的主要思路是在内存中开辟一块与显存中大小一致的内存区域,一般使用BitMap类来创建这个内存区域,即在内存中开辟一块虚拟画布,然后将所有需要画的图元一个个先画在这块“虚拟画布”上,最后在一次性将整块“虚拟画布”画到真正的窗体上。因为所有的单个图形的绘制都不是真正的调用显示系统来“画”,所以不会占用显示系统的开销,极大的提高的绘图效率,避免闪烁,不流畅等现象。使用双缓冲绘图的主要代码如下:
Bitmap bitmap=new Bitmap(this.width,this.height);∥创建一个与窗口大小相同的虚拟画布
Graphics bg=Graphics.Fromhnage(bitmap);∥在这个画布上创建画板
bg.FillRectangle(b1,rect);∥在虚拟画布上绘制矩形
g.DrawImage(bitmap,0,0);∥将内存中绘制好的图形输出到屏幕
双缓冲技术有效的解决了GDI+绘图时的屏幕闪烁问题,但是DrawImage函数效率十分低下,拖慢了内存图形画到显存中进行显示的效率,解决的办法是引入GDI的绘图函数bitblt来进行从内存中向显存中进行绘图。bitblt是gdi32.dll中的一个函数,可以大大提高内存图形向显存的传输速度。为了区分三种不同的绘图方式,创建了三个panel,并分别在这三个panel上绘制矩形,红色矩形是直接绘制,黄色矩形为双缓冲方式绘制,蓝色矩形的绘制使用了bitblt函数。
3.绘图效率比较
为了比较三种不同方式的绘图效率,本了以下实验。使用GDI+绘制一个图形界面,该实验主要在一个600×600的区域内每隔10ms绘制60×60个圆,每隔10ms改变其颜色(红和蓝两种颜色)。统计每帧的绘图时间,实时计算帧速,得到的结果如图2图4所示。
可以看到,采用直接绘制的方式,绘图效率非常低,平均帧速只有4帧/s左右,而且闪烁的现象非常的明显;而使用双缓冲技术绘图则有效的解决闪烁的问题,绘图效率也有所提高,帧速达到了20帧/s左右;而bitblt函数则进一步提高了程序的绘图效率,帧速达到了40帧/s左右。
4.结论
GDI+绘图引擎由于其易用性和与C#的良好集成,在信号处理软件的开发中可以很好的承担二维信号图形的绘制。但是直接绘图的方式绘制动画效率低下且容易产生图片闪烁的问题。使用双缓冲技术可以有效的消除闪烁并提高绘图效率;而使用bitblt函数代替DrawImage函数则可以进一步提高GDI+的绘图效率。本文对三种不同的绘图方式进行了详细的阐述,并编写了一个实验程序比较了三种方式的优劣。实验程序表明,使用双缓冲+bitblt的方式,绘图性能最好。