GDI 效率問題與優化

2021-06-22 16:37:00 字數 4276 閱讀 7419

這週在用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 在資料處理時回需額外...