[转]怎样提高GDI+的绘图效率
之前是提出的问题。现在把它放在博客上咧:
最近用GDI+绘图,初次使用,感觉绘制效率不太满足要求。搜索了些相关资料,多数也只谈到了使用双缓冲(仅仅是解决了画面的闪烁问题)。了解到DirectX绘制要快的多(picasa 就使用的DirectX),但好象没有这个必要,毕竟偶只是在窗口中绘制有动画效果的2维图片。认真研究了一番,也总结了一些提高效率的方法。如果哪位高手有更好的建议,希望指点一二,偶的这篇文章算是抛砖引玉:)
先描述下问题域:在一幅背景画面上有几个圆形按钮,这几个圆形按钮绕成一个大圆环,要做出的效果是:点击按钮,所有的按钮都沿大圆环转动。当然,其过程要平滑。
起初,不知道绘制图片的时间大多浪费的什么地方,一步步摸索,相关资料也是少的可怜啊!
我的解决方法:
1、在对话框初始化的时候,加载图片(包括背景图片、圆形按钮的图片),用类成员指针记录下来。
2、在OnPaint中,把背景和圆形按钮的图片都绘制一次,在内存中把按钮绘制到背景图片的相应的位置上(位置已经计算好了),再一次性画到屏幕上。像这样:
CDC* pDC = GetDC();
Graphics graphics (pDC-> GetSafeHdc());
// 设定裁剪区域(这个区域我剪切成了一个圆环,目的就是提高绘制速度,反复绘制时,只绘制这个圆环区域)
if (!bDrawBkGrd)
graphics.SetClip (m_pClipRgn);
// 内存中绘制
Image* pImg = m_pBkImg-> Clone (); // 不消耗CPU时间
Graphics* pGraphics = graphics.FromImage (pImg);
for (int i = 0; i < 7; i++)
{
pGraphics-> DrawImage (m_pImg[i], m_place[i].X, m_place[i].Y, m_pImg[i]-> GetWidth(), m_pImg[i]-> GetHeight());
}
// 绘制到屏幕
graphics.DrawImage (pImg, 0, 0, pImg-> GetWidth(), pImg-> GetHeight());
delete pGraphics;
delete pImg;
ReleaseDC (pDC);
这样反复绘制时的效果不会闪烁,呵呵。
3、但绘制速度不快,大概是12.5帧/秒。背景图片是1027 X 768的PNG图片,按钮图片是100 X 110的jpg图片,我的机器是P4 1.7G,512内存,显卡是NVIDIA TNT2,绘制效率低了点。
4、一定还能提高帧速,俺研究了半天,试了下CachedBitmap,代码改为:
CDC* pDC = GetDC();
Graphics graphics (pDC-> GetSafeHdc());
// 设定裁剪区域(这个区域我剪切成了一个圆环,目的就是提高绘制速度,反复绘制时,只绘制这个圆环区域)
if (!bDrawBkGrd)
graphics.SetClip (m_pClipRgn);
// 内存中绘制
Image* pImg = m_pBkImg-> Clone (); // 不消耗CPU时间
Graphics* pGraphics = graphics.FromImage (pImg);
for (int i = 0; i < 7; i++)
{
CachedBitmap cachedBitmap((Bitmap*)m_pImg[i], &graphics);
pGraphics-> DrawCachedBitmap (&cachedBitmap, m_place[i].X, m_place[i].Y);
}
// 绘制到屏幕
graphics.DrawImage (pImg, 0, 0, pImg-> GetWidth(), pImg-> GetHeight());
delete pGraphics;
delete pImg;
ReleaseDC (pDC);
果然!呵呵,帧速提高到了15.5帧/秒
5、总结了这些经验,希望能够和大家分享下。上面的代码是包装在一个函数中的。让触发事件来调用,在OnPaint中也有调用。如果哪位高手有什么好的建议的话,还望不吝赐教!帧速越高越好啊,不知道用GDI+速度能够提高到多少:)24帧以上最好了!
发表于 @ 2008年01月10日 14:22:00
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kaka_iseeyou/archive/2008/01/10/2033686.aspx