這週在用gdi+實現的動畫效果,起初每畫一幀都在30-40ms左右,動畫效果自然不能令人滿意。
困惑了良久,後面在高人的指點下,效率有了顯著地提高,最主要是清楚了時間都花在了那裡,優化起來也就方便很多。
我現在知道的影響gdi+效率的主要有:
1、drawimage,比起bitblt實在差的不是一點點,解決的方法就是用bitblt替換drawimage。
2、pixelformat ,原來沒想到這個也會影響效率,但事實證明確實是這樣。
bitmap在new出來的時候是和本身的格式有關的,但在最終畫到dc上的可不一定是這個格式,具體的格式請查閱msdn:image pixel format constants
如果格式不對,drawimage時會自己做一次格式轉換,這個也會浪費一定的時間。
乙個做法就是bitmap在new出來後用clone到乙個新的 bitmap,這時是可以轉換成指定的pixelformat的:)
統一成一種格式,特別是大圖的時候,效果比較明顯。
3、盡量用cachedbitmap替代直接的bitmap使用也能優化一些效率。
4、每次都全部重畫是一種浪費,能不重畫的就不重畫,重新整理的區域也是優化的乙個有效方式。
5、物件的構造比較費時,比如用於雙緩衝的記憶體bitmap和graphics最好設成成員變數,而不是在onpaint中每次新建
6、減小大小 :) ……
關於gdi和gdi+
gdi的效率更高,而gdi+無疑更加易用,魚與熊掌不可兼得。
我現在的做法是用gdi+畫到記憶體bitmap上,最後用gdi bitblt畫到dc上。
小結:最開始很鬱悶,怎麼優化都不見效果,感覺亂成一團,於是不斷地msdn,google,找人……
終於,在理清大部分的細節後發現:答案其實也很簡單。
事情還沒結束,今天也太晚了,就先寫個大概,備忘下,下次有空時再整理個例子出來。希望大家批評指正。
感謝老師給我的幫助:)
2009-07-05 0:31 --the end--
// 新增於2009/7/31
把gdi+轉成gdi來畫到dc上的**片段,希望對大家有所幫助。
code highlighting produced by actipro codehighlighter (freeware)>/*
@ function : createdib
@ brief : 建立記憶體位圖
@ parameter : w
@ parameter : h
@ parameter : [out] hbmpsection onpaint中會把這個位圖直接往dc上貼
@ parameter : [out] bmpdata 點陣圖的實際資料,gdiplus的會把東西都話到上面
@ return :
@ remark :
@*/
bool createdib(int w, int h, out hbitmap& hbmpsection, out byte** bmpdata)
;
info.bmiheader.bisize = sizeof(info.bmiheader);
info.bmiheader.biwidth = w;
info.bmiheader.biheight = -h;
info.bmiheader.biplanes = 1;
info.bmiheader.bibitcount = 32;
info.bmiheader.bicompression = bi_rgb;
info.bmiheader.bisizeimage = w * h * 32 / 8;
hdc hdc = ::getdc(null);
hbmpsection = ::createdibsection(hdc, &info, dib_rgb_colors, (void**)bmpdata, null, 0);
::releasedc(null, hdc);
return hbmpsection != null;
}
/*
@ function : flushtodib
@ brief : 將gdiplus的bitamp轉存到gdi的記憶體點陣圖上
@ parameter : [in] pmembitmap
@ parameter : [in, out] bmpdata 就是上面的函式建立處理的記憶體點陣圖的資料區
@ return :
@ remark :
@*/
void flushtodib(in bitmap* pmembitmap, in out byte** bmpdata)
// m_hbmpsection是initdialog時用createdib建立出來的
lresult onpaint(uint umsg, wparam wparam, lparam lparam, bool& bhandled)
/* @ function : createdib
@ brief : 建立記憶體位圖
@ parameter : w
@ parameter : h
@ parameter : [out] hbmpsection onpaint中會把這個位圖直接往dc上貼
@ parameter : [out] bmpdata 點陣圖的實際資料,gdiplus的會把東西都話到上面
@ return :
@ remark :
@*/
bool createdib(int w, int h, out hbitmap& hbmpsection, out byte** bmpdata)
; info.bmiheader.bisize = sizeof(info.bmiheader);
info.bmiheader.biwidth = w;
info.bmiheader.biheight = -h;
info.bmiheader.biplanes = 1;
info.bmiheader.bibitcount = 32;
info.bmiheader.bicompression = bi_rgb;
info.bmiheader.bisizeimage = w * h * 32 / 8;
hdc hdc = ::getdc(null);
hbmpsection = ::createdibsection(hdc, &info, dib_rgb_colors, (void**)bmpdata, null, 0);
::releasedc(null, hdc);
return hbmpsection != null;
} /*
@ function : flushtodib
@ brief : 將gdiplus的bitamp轉存到gdi的記憶體點陣圖上
@ parameter : [in] pmembitmap
@ parameter : [in, out] bmpdata 就是上面的函式建立處理的記憶體點陣圖的資料區
@ return :
@ remark :
@*/
void flushtodib(in bitmap* pmembitmap, in out byte** bmpdata)
// m_hbmpsection是initdialog時用createdib建立出來的
lresult onpaint(uint umsg, wparam wparam, lparam lparam, bool& bhandled)
以上**是從我自己的工程中抽取出來的,沒有定義的變數請自行處理。
最近太忙沒空也懶得去抽成乙個簡單的例子。但最重要的部分已經都在上面的**中呈現。
再囉嗦下我的的使用流程:
1、initdialog中用createdib建立出hbmpsection,並得到他的bmpdata
2、程式的否個地方把你的東西畫到gdi+的bitmap上
3、呼叫flushtodib,把你的bitmap寫到第一步的bmpdata中
4、onpaint中間hbmpsection用bitblt到dc上
GDI 編譯問題
當寫乙個gdi 的程式時,如果編譯的過程中出現一大堆的錯誤,如 1 c program files microsoft sdks windows v6.0a include gdiplusimaging.h 74 error c4430 缺少型別說明符 假定為 int。注意 c 不支援預設 int ...
使用limit效率的問題和優化
limit用來返回select語句的行數。limit取1個或2個數字引數,如果給定2個引數,第乙個指定要返回的第一行的偏移量,第二個指定返回行的最大數目。初始行的偏移量是0 不是1 limit在可以很方便的返回所需的資料,資料量小 10w以下 時,效率這方面不會有太大的問題,但資料量一大就會導致效能...
索引效率優化
索引是提高資料查詢最有效的方法,也是最難全面掌握的技術,因為正確的索引可能使效率提高10000倍,而無效的索引可能是浪費了資料庫空間,甚至大大降低查詢效能。索引的管理成本 1 儲存索引的磁碟空間 2 執行資料修改操作 insert update delete 產生的索引維護 3 在資料處理時回需額外...