关于GDI+的那些事(1)——效率、双缓冲
来源:互联网 发布:云端软件平台pc 编辑:程序博客网 时间:2024/06/05 16:19
前言:
一年来做了一些图像相关的工作,最开始也没什么基础,所以本着简单质朴的理念没有试用那些第三方图像处理库,而是选用了windows提供的GDI/GDI+,结果也能胜任需要。
这玩意嘛,上手也不难,用几天后,说实话,真感觉像网上一些人说的那样,“挺垃圾的”。
由于接下来很可能转行了,一些一直没想清楚也没机会求解答的问题就只能存疑了,比如:
1,到底是我对GDI/GDI+的了解不够深入,导致自认为它“垃圾”,还是它确实很差?
2,那些第三方图像库的实现机制是怎样的?它们在windows系统对底层的封闭态度下,如何做到类似控制显存等?
这个系列的文章,记录个人一些浅薄的经验心得,不算太透彻,甚至都不够准确,仅供参考罢了。
一、效率及“双缓冲”
只要用几天GDI+,我想几乎所有人都会遇到类似“画面闪烁”、“帧率低”等问题,然后上网一搜,就会搜到一堆“双缓冲”、“提高效率”的字眼。
这里就存在一个问题,因为你的“闪烁”和我的“闪烁”,其实是两种现象,而甲的“双缓冲”和乙的“双缓冲”,又完全是两码事。这里理一理:
A.第一种类型的“闪烁”及“双缓冲”:
比如你要在白的客户端背景上移动一幅图片。
很明显,需要擦除、重绘,如此循环实现。但是这样做就会产生一个问题,移动的过程中图片一闪一闪的,眼都花了。这是因为擦除完毕后白板状态也实时被呈现出来,你眼睛看到的是白板-图片-白板-图片,自然闪烁。
解决的方法,是在内存开辟一幅草稿图,每次擦除重绘,都在草稿上进行,而前台客户端呢,仅仅是周期的贴上草稿纸。这样你眼睛看到的是 草稿纸-新的草稿纸-新的草稿纸……这样就不闪了。
B.第二种类型的“闪烁”及“双缓冲”:
第二种闪烁发生在直接用Graphics对象的DrawImage方法绘制屏幕时,当然Graphics对象根据客户端窗口句柄生成的。
你会发现屏幕也在闪,但是不同于前一种,是那种感觉屏幕上的图像被分割成一条一条的“闪烁”。
我曾经以为这是因为DrawImage的绘制效率太低导致,然后改用GDI的BitBlt函数自己封了一个DrawScreen绘图函数,“成功”解决了此“闪烁”。
(在此插一句,我做过一个测试,先都预加载好图片,然后DrawImage和BitBlt均绘制几百次,对比其效率,发现相差有4倍左右)
昨天我重新对比测试了DrawScreen和DrawImage的效率,发现DrawScreen反而慢了近六倍。
实际上,真正的“闪烁”原因,这篇文章给出的解释比较合理:使用bitblt提高GDI+绘图的效率(转)
“GDI+画图,是将所有的图形先换入显卡的缓存中看,显卡会每隔一段时间将显存中的内容输出到显示器中,如果在这个显示周期内,无法将所有的图形都放到显存中,就会出现闪烁的现象”
它提出的解决方案,又是一种概念的“双缓冲”,这里我贴出我自己的DrawScreen,原理类似。
void DrawScreen(Image *image){bitmap = (Bitmap *)image; //image转为bitmapbitmap->GetHBITMAP(Color(0,0,0), &hBitmap); //获取bitmap对应GDI位图句柄CDC *cdc = GetDC(); //创建目标dcHDC srchdc = CreateCompatibleDC(cdc->m_hDC); //创建源dcSelectObject(srchdc, hBitmap); //将源位图句柄选入源dcBitBlt(cdc->m_hDC, 0, 0, CLIENT_WIDTH, CLIENT_HEIGHT, srchdc, 0, 0, SRCCOPY);//绘图DeleteObject(hBitmap);DeleteDC(srchdc);ReleaseDC(cdc);}
所以实质上是牺牲了效率解决了闪烁问题,至于典型的利用BitBlt方法提高效率的例子,我还真给不出。
最后再贴篇我觉得比较专业的文章供参考:陈灯WGF工作内容及特点
这个叫陈灯的博主的blog中,还有其他论述此问题的文章,自己找吧。
- 关于GDI+的那些事(1)——效率、双缓冲
- 利用GDI+的双缓冲技术来提高绘图效率
- 利用GDI+的双缓冲技术来提高绘图效率
- 利用GDI+的双缓冲技术来提高绘图效率
- 利用GDI+的双缓冲技术来提高绘图效率
- 关于GDI+的那些事(2)——创建空白Image
- 关于GDI+的那些事(3)——在内存中将bmp数据压缩为jpeg
- .NET/GDI+的双缓冲
- .NET/GDI+的双缓冲
- GDI双缓冲的实现
- 陈灯WGF双缓冲绘图框架之gdi及gdiplus实现双缓冲时存在的效率问题及解决办法
- 利用GDI+的双缓冲技术来提高绘图效率(转)
- 利用GDI+的双缓冲技术来提高绘图效率(转)
- Gdi+与双缓冲的图片显示(应用篇)
- Gdi+与双缓冲的图片显示(应用篇)
- 效率,还是效率 .NET Compact Framework下实现GDI双缓冲
- C#: GDI+双缓冲技术的使用
- GDI+中双缓冲的基本写法
- Android Studio右键选项中没有Git?
- mysql导入数据方法mysqlimport
- Mips/MHz
- ADS(AXD)调试出现 DBE Warning 00067
- 数字视频基础(三)
- 关于GDI+的那些事(1)——效率、双缓冲
- MTK之camera框架
- 数字视频基础(四)
- 客客安装英文语言包
- WinDbg双机调试,很慢
- sql之left join、right join、inner join的区别
- Unity中的 HideInInspector和SerializeField 用法
- 数据库移植遇到的问题
- Android上实现仿IOS弹性ScrollView