UI 动画特效及效率探讨

本文探讨了UI动画特效的效率提升,通过GDI和GDI+的比较,展示了如何使用CachedBitmap提高Windows应用程序的绘图速度。接着,文章转向Android平台,介绍了SurfaceView的工作原理和优势,说明了SurfaceView如何用于实现高性能、可控制帧率的动画,强调了其在游戏和高帧率应用中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NOTE: 动画特效的原理:简单的:逐帧绘制,复杂的 调研3D库的实现

目前的调研是两个方面,一,windows的 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帧以上最好了!


 偶贴的上一个帖子名字是“GDI+的绘图效率问题,大家讨论一下吧!”。在其中解决的效率问题远远不够。现在工作中的模块做的差不多了,总结了一下最近得到的经验结论,贴出来大家进一步讨论下。。。也算是在优快云上得到了诸多帮助的一个小小的回报:) 在交流中共同进步吧! 

  不知道为什么MS把GDI+中的   DrawImage   这个函数效率做的这么低,(当然了,它的优点是使用方便、支持透明PNG格式等等,还有什么优点有经验的朋友不妨贴出来共享下:) 那么到底有多低呢?我也不知道,所以刚才做了个试验。让DrawImage和::BitBlt速度做了个比较! 

  先说下我的机器配置:2*3.0G   Intel   CPU,1G的内存,Intel945的显卡。在一个窗口中用DrawImage画一个590X480大小的PNG图片,画了100次,用了.......长时间;用BitBlt画同样大小的bmp图片,画了1000次,用了...长时间,多少时间我不管了,帧速我是计算出来了大约是   DrawImage   16.5帧/秒,BitBlt   2169.2帧/秒   。没错!确实是这个数字。我数学学的不好,就用计算器算了一下BitBlt的绘图速度是DrawImage的131.5倍。。。 

  代码也贴出来吧,写的比较粗糙: 

void   CCmpBitBltToDrawImageDlg::OnBnClickedButton1() 


Bitmap*   ppng   =   NULL; 
CDC*   pDC   =   GetDC   (); 
Graphics*   pGrp   =   Graphics::FromHDC   (pDC-> GetSafeHdc   ()); 
ppng   =   Bitmap::FromFile   (L"res//tray.png"); 

clock_t   start   =   clock   (); 
for   (int   i   =   0;   i   <   100;   i++) 

pGrp-> DrawImage   (ppng,   0,   0); 

delete   pGrp; 
ReleaseDC   (pDC); 
delete   ppng; 

clock_t   time   =   clock   ()   -   start; 
float   ftime   =   time   /   1000.0f; 
CString   str; 
str.Format   ("%.1f   frame   per   second/n",   100   /   ftime); 
AfxMessageBox   (str); 


void   CCmpBitBltToDrawImageDlg::OnBnClickedButton2() 

CDC   memDC; 
CBitmap   bmp; 

if   (0   ==   bmp.LoadBitmap   (IDB_BITMAP1)) 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值