`
isiqi
  • 浏览: 16054361 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

利用GDI+的双缓冲技术来提高绘图效率

阅读更多
专栏作品
利用GDI+的双缓冲技术来提高绘图效率
卢彦

前言

进入.NET时代,Windows的绘图技术也从GDI升级到了GDI+,从名字就能知道GDI+是对以前传统GDI绘图技术的一次升级,不过在微软几乎把所有的新技术都冠之.NET的情况下,GDI+竟然不叫做GDI.NET,还真让我感到有点意外了。 :)

GDI+在一种与设备无关的环境下提供了一套统一的绘图编程模型,极大的提高了Windows绘图编程的方便性,我们再也不用创建什么各种各样复杂的设备环境了,说实话,我现在想起来都头疼。

题归正传,关于如何进行GDI+的基本编程,我不能过多的加以描述,如果有对此概念还不太清楚的朋友,建议先去了解一下相关的资料,我们在这里主要讨论的是一种提高绘图效率(主要是动画效率)的双缓冲技术在GDI+中的应用和实现。

实现目的

为了能清楚的对比应用双缓冲技术前后的效果,我编写了一段程序来进行测试。首先,我创建了一个普通的Windows Application,在主Form中,我放置了一个定时器:timer1,然后将它的Interval属性设置为10,然后在Form上放置两个按纽,分别用来控制定时器的开启和关闭,最后,我还放置了一个label控件,用来显示绘图的帧数。

测试程序

在timer1的timer1_Tick事件中,我写下了如下的代码(其中flag是一个bool型标志变量):

DateTime t1 = DateTime.Now;
Graphics g = this.CreateGraphics();
if(flag)
{
	brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), 
		new PointF(700.0f, 300.0f), Color.Red, Color.Blue);
	flag = false;
}
else
{
	brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), 
		new PointF(700.0f, 300.0f), Color.Blue, Color.Red);
	flag = true;
}
for(int j = 0; j < 60; j ++)
{
	for(int i = 0; i < 60; i++)
	{
		g.FillEllipse(brush, i * 10, j * 10, 10, 10);
	}
}
DateTime t2 = DateTime.Now;
TimeSpan sp = t2 - t1;
float per = 1000 / sp.Milliseconds;
this.label1.Text = "速度:" + per.ToString() + "帧/秒";

运行后,我点击“开始”按纽,效果如下图所示:

应用双缓冲以前的效果图(帧数:5帧/秒)

正如大家所看到的,我在程序中使用循环画了几百个圆形,然后在每次的定时器脉冲事件中使用不同方向的线性渐变来对它们进行填充,形成了一个动画效果。不过不幸的是,程序运行起来闪烁很严重,几乎每次刷新的时候都可以看到一条很明显的扫描线从上慢慢的刷到下来完成整幅图形的刷新动作。如果你不是要模拟老式雷达的区域扫描的话,这种速度不会满足你的要求。

改进代码

下面是我改进以后的代码:

DateTime t1 = DateTime.Now;
Bitmap bmp = new Bitmap(600, 600);
Graphics g = Graphics.FromImage(bmp);
if(flag)
{
	brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), 
			new PointF(700.0f, 300.0f), Color.Red, Color.Blue);
	flag = false;
}
else
{
	brush = new LinearGradientBrush(new PointF(0.0f, 0.0f), 
			new PointF(700.0f, 300.0f), Color.Blue, Color.Red);
	flag = true;
}
for(int j = 0; j < 60; j ++)
{
	for(int i = 0; i < 60; i++)
	{
		g.FillEllipse(brush, i * 10, j * 10, 10, 10);
	}
}
this.CreateGraphics().DrawImage(bmp, 0, 0);
DateTime t2 = DateTime.Now;
TimeSpan sp = t2 - t1;
float per = 1000 / sp.Milliseconds;
this.label1.Text = "速度:" + per.ToString() + "帧/秒";

运行后,我点击“开始”按纽,效果如下图所示:

应用双缓冲以后的效果图(帧数:9帧/秒)

经过改进后,画面刷新速度大大加快,绝对看不到任何的“扫描线”,帧数也从5帧一下就提高到了9帧,几乎是两倍于前的速度。这究竟是什么原因呢?让我来讲述其中的道理。

因为圆是要一个一个画上去,所以每画一个圆,系统就要做一次图形的绘制操作,图形的重绘是很占用资源的,当需要重绘的图形数量很多的时候,所造成的系统开销就特别大,造成我们看到的那种刷新缓慢的情况。那么如何来解决这个问题呢?

答案就是双缓冲,何谓“双缓冲”?它的基本原理就是:先在内存中开辟一块虚拟画布,然后将所有需要画的图形先画在这块“虚拟画布”上,最后在一次性将整块画布画到真正的窗体上。因为所有的单个图形的绘制都不是真正的调用显示系统来“画”,所以不会占用显示系统的开销,极大的提高的绘图效率。

实现双缓冲的具体步骤

我再来详细解释一下刚才实现双缓冲的具体步骤:

1、在内存中建立一块“虚拟画布”:

Bitmap bmp = new Bitmap(600, 600);

2、获取这块内存画布的Graphics引用:

Graphics g = Graphics.FromImage(bmp);

3、在这块内存画布上绘图:

g.FillEllipse(brush, i * 10, j * 10, 10, 10);

4、将内存画布画到窗口中

this.CreateGraphics().DrawImage(bmp, 0, 0);

总结

怎么样?是不是很简单?但是正是这个简单的操作大大提高了绘图效率,所以如果你需要进行GDI+图形编程,双缓冲技术一定要掌握,特别是在进行大量图形绘制刷新的情况下要尽量采用。

2004年1月6日 0:14 - (阅读:10243;评论:25)
<link href="http://blog.joycode.com/5drush/Services/Pingback.aspx" rel="pingback"> <!-- <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"> <rdf:Description rdf:about="http://blog.joycode.com/5drush/articles/10701.aspx" dc:identifier="http://blog.joycode.com/5drush/articles/10701.aspx" dc:title="利用GDI+的双缓冲技术来提高绘图效率" trackback:ping="http://blog.joycode.com/5drush/services/trackbacks/10701.aspx" /> </rdf:RDF> -->

反馈

可不可以发个源代码给我
Email: ffoieoi@hotmail.net

#小心GDI 资源泄漏 2004-8-19 2:36 ashchan
Ping Back来自:blog.csdn.net

#re: 利用GDI+的双缓冲技术来提高绘图效率 2004-8-19 2:38 ashchan
您的例子中双缓冲部分会引起内存泄漏,详情请见http://blog.csdn.net/ashchan/archive/2004/08/19/GDIPlus_Leak.aspx

#小心GDI 资源泄漏 2004-8-19 15:56 yolle
Ping Back来自:blog.csdn.net

#re: 利用GDI+的双缓冲技术来提高绘图效率 2004-8-20 17:06 sanway
用这个好多了,测试后证明的。

this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);


#re: 利用GDI+的双缓冲技术来提高绘图效率 2004-9-24 13:15 Qifang
=======================================
WWW.ITZYK.NET IT资源库 ----> 专业的DoNet技术论坛
=======================================
www.itzyk.net 是一个刚刚创建起来的专业DoNet技术论坛,讨论与交流各种关于DoNet技术方面的信息,由于论坛正在起步阶段,需要大量高手,牛人们前来相助,特此诚邀各位兄弟姐妹们来参与论坛的建设,一起来打造属于我们的程序员们的专业技术论坛。

#re: 利用GDI+的双缓冲技术来提高绘图效率 2004-10-30 17:00 郭龙
这种在内存中绘图的技术最多用在桌面应用程序中,对于游戏和真正的绘图引擎根本不能相提并论,所以提高什么绘图效率没有意义。再说在内存中的点阵不能直接与显存中的direct点阵相提并论。
现在显卡都是用了<5。0nm显存agp接口,以块传输方式,让显卡自己去读内存,一点都不耗cup而且速度不会小于1024*768*16*60。
所以大家一定记着绘图就用directx千万不要用gdi。

#利用GDI 的双缓冲技术来提高绘图效率(转) 2005-9-12 15:10 kaixin110
Ping Back来自:blog.csdn.net

#re: 利用GDI+的双缓冲技术来提高绘图效率 2005-9-16 22:49 noslopforever
手动创建交换链?
GDI+是用DD7做底层实现的,一定提供了自动交换链的方式。如果要手动创建交换链,效率怎么都不可能比硬件自动交换链快的。
而且GDI+绝不会因为画几百个圆性就下10帧的……
不过仍然顶一个,加油~

#re: 利用GDI+的双缓冲技术来提高绘图效率 2005-10-25 1:52 sunby
GDI+竟然不叫做GDI.NET,还真让我感到有点意外了。 :)

不是一个层面的东西,功力不够啊!


#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-1-13 19:42 x
I don't understand.

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-4-10 14:55 3546465
64546546

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-5-29 23:19 www
请问如何用vb.net 或c#实现直接在桌面上画图?,或者打开一个winForm,要透明的,然后在上面画图,而画的图却不透明?

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-6-5 11:03 wj
最后一个问题真的很菜

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-6-21 11:36 king
如果再配合多线程是不是能效果更好呢

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-8-15 20:25 lemon
to sanway:
我加了你说的那几个SetStyle方法,没用阿


#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-8-28 0:28 a
xiao xue sheng

#re: 利用GDI+的双缓冲技术来提高绘图效率 2006-9-12 15:32 leon
能否与GDI双缓冲对比一下?

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2006-12-13 22:42
不懂。菜啊。。。。。。。。。。。。。。。

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2006-12-13 22:42
不懂。菜啊。。。。。。。。。。。。。。。

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2006-12-25 16:29 .....
我看上面那位叫"郭龙"的先生对这个问题的分析很到位而且也很正确,有机会一起探讨探讨啊.

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2007-1-6 9:40 再来*不难
不好意思今天才看到了效果。
双缓冲技术?
我有点怀疑了:
我验证了一下:
1。循环中的
for (int j = 0; j < 60; j++)
{
for (int i = 0; i < 60; i++)
{
g.FillEllipse(brush, i * 10, j * 10, 10, 10);
}
}
改为
for (int j = 0; j < 60; j++)
{
for (int i = 0; i < 60; i++)
{
gP.AddEllipse(i * 10, j * 10, 10, 10);
}
}
g.FillPath(brush, gP);
2再把用了Bitmap的方法来改为上面的(代码略)
结果如下:我电脑上源贴结果分别为4-6帧/秒和9-12帧/秒
我改后的结果均为16-21帧/秒
希望大家验证所谓的双缓冲技术。

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2007-1-6 9:54 再来不难
用了这个闪得更快,每秒帧数却没有变。
public void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}
初学,我不是太懂,所以请赐教!

#回复: 利用GDI+的双缓冲技术来提高绘图效率 2007-1-15 15:06 DM Chen
可以把源代码给我一份吗?
w81211984@126.com


#回复: 利用GDI+的双缓冲技术来提高绘图效率 2007-3-3 14:38 caojie
做了一个屏幕作图的软件,发现将image作为缓冲,当需要多次重绘而使用drawimage贴图特别的慢,耗资源,用GDI将一副位图选入memDC,然后graphics g(memDC.mhDC);然后在缓冲中作图,在重绘时用bitblt速度快,而且耗资源少
正像书上说的GDI+ 1.0使用于对速度要求不高的场合,我只好用GDI和GDI+来个拼接,不会OPENGL技术,不知道在GDI+中是不是由更好的方法了?


#回复: 利用GDI+的双缓冲技术来提高绘图效率 2004-6-24 16:54 good
分享到:
评论

相关推荐

    前18大旋转修整器企业占据全球87%的市场份额.docx

    前18大旋转修整器企业占据全球87%的市场份额

    Planet-SkySat-Imagery-Product-Specification-Jan2020.pdf

    SKYSAT IMAGERY PRODUCT SPECIFICATION PLANET.COM VIDEO Full motion videos are collected between 30 and 120 seconds by a single camera from any of the active SkySats. Videos are collected using only the Panchromatic half of the camera, hence all videos are PAN only. Videos are packaged and delivered with a video mpeg-4 file, plus all image frames with accompanying video metadata and a frame index file (reference Product Types below)

    Screenshot_20240506_133458_com.netease.yhtj.vivo.jpg

    Screenshot_20240506_133458_com.netease.yhtj.vivo.jpg

    2019年A~F题特等奖论文合集.pdf

    大学生,数学建模,美国大学生数学建模竞赛,MCM/ICM,历年美赛特等奖O奖论文

    雷达物位变送器安装和操作手册

    雷达物位变送器安装和操作手册

    node-v11.6.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Python3实现快速排序(源代码)

    快速排序是一种基于分治策略的排序算法,通过选择一个基准元素,将待排序的数组划分为两个子数组,一个包含所有小于基准的元素,另一个包含所有大于基准的元素,然后递归地对这两个子数组进行快速排序。快速排序在平均情况下具有O(n log n)的时间复杂度,是一种非常高效的排序算法。然而,在最坏情况下,当输入数据已经有序或接近有序时,快速排序的性能会退化为O(n^2)。此外,快速排序是不稳定的排序算法,即相等的元素可能在排序过程中改变相对位置。尽管如此,快速排序仍然因其高效的平均性能而在实际应用中广泛使用。在Python3中,可以通过递归或迭代的方式实现快速排序算法,但为了避免额外的空间开销,通常会采用原地排序的方式来实现。

    毕业课设基于51单片机的出租车计价器(昼夜)

    【作品名称】:基于51单片机的出租车计价器(昼夜) 含(程序、仿真图、流程图、原理图) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 出租车计价器: 1、不同情况具有不同的收费标准,具有白天和夜晚不同的计价能力 2、能进行手动修改单价 3、具有数据的复位功能(起步价,起步公里数,里程单价,白天晚上不一样) 4、能够在掉电的情况下存储单价等数据 5、步进电机模拟里程,一圈表示一里路

    2024年中国API 11P往复式气体压缩机行业研究报告.docx

    2024年中国API 11P往复式气体压缩机行业研究报告

    Windows 10系统上安装和配置Tomcat的步骤

    附件是Windows 10系统上安装和配置Tomcat的步骤,文件绿色安全,请大家放心下载,仅供交流学习使用,无任何商业目的!

    广东工业大学《计算网络A》实验报告期末考试试题回忆版.doc

    此试题是考试后回忆版本,你会发现是惊喜。恭喜你考个好成绩。

    数据库+人大金仓+Linux系统安装

    数据库+人大金仓+Linux系统安装

    2023年美赛特等奖论文-C-2309397-解密.pdf

    大学生,数学建模,美国大学生数学建模竞赛,MCM/ICM,2023年美赛特等奖O奖论文

    opencv-python-4.5.4.60-cp36-cp36m-win-amd64.whl

    opencv-python-4.5.4.60-cp36-cp36m-win-amd64.whl

    减肥管理,全球前10强生产商排名及市场份额.docx

    减肥管理,全球前10强生产商排名及市场份额

    上海大学大学生创新创业训练计划申请书(创新训练项目).doc

    内容概要:《上海大学大学生创新创业训练计划申请书(创新训练项目)》是用于申请参加上海大学的大学生创新创业训练计划的申请书,旨在帮助学生提出创新项目计划,获得培训和支持,促进学生创新创业能力的提升。 适用人群:适合上海大学的在校大学生,特别是对创新创业感兴趣、有创新想法和创业计划的学生,希望通过该计划获得指导和资源支持,实现自己的创业梦想。 使用场景及目标:申请书的使用场景是为了参加上海大学的大学生创新创业训练计划,目标是通过提交详细的创新项目计划,获得评审通过并获得培训、指导和资金支持,从而推动学生的创新创业实践和能力提升。 其他说明:申请书应包括清晰的创新项目描述、项目可行性分析、预期目标和计划、团队介绍等内容,以展现学生的创新能力和项目潜力。申请书的撰写需要认真准备,体现出学生对创新创业的热情和才华,以提高申请成功的机会。

    IEC 60364-7-716-2023 第7-716部分:特殊装置或场所要求.信息和通信技术ICT电缆基础设施上ELV直流配电

    IEC 60364-7-716-2023 低压电气装置.第7-716部分:特殊装置或场所的要求.信息和通信技术(ICT)电缆基础设施上的ELV直流配电.pdf

    IEC PAS 61851-1-1 2023 电动汽车导电充电系统.第1-1部分:使用4型车辆耦合器电动汽车导电带电系统特殊要求

    IEC PAS 61851-1-1 2023 电动汽车导电充电系统.第1-1部分:使用4型车辆耦合器的电动汽车导电带电系统的特殊要求.pdf

    前11大客运渡轮服务企业占据全球30.3%的市场份额.docx

    前11大客运渡轮服务企业占据全球30.3%的市场份额

    wsl+MCgpu安装记录

    wsl+MCgpu安装记录

Global site tag (gtag.js) - Google Analytics