當(dāng)前位置:
首頁 >
Windows Mobile的高效贴图
發(fā)布時(shí)間:2025/3/20
48
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Windows Mobile的高效贴图
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Windows Mobile的高效貼圖?
原文:http://www.cppblog.com/guogangj/archive/2010/06/20/118316.html
我最近接手了一個(gè)項(xiàng)目,是Windows Mobile平臺(tái)的,主要做UI美化,貼圖是其中的一大塊,我遇到的最大的問題就是貼圖的效率問題,如何將一張內(nèi)存里的圖片高效繪制出來,實(shí)現(xiàn)平滑流暢的UI動(dòng)畫效果。我嘗試了許多辦法,甚至DirectDraw,但我發(fā)覺在硬件不支持的情況下,DirectDraw除了讓代碼變得更復(fù)雜之外,沒有任何優(yōu)點(diǎn)。好,接下去我們來分析一下如何盡量發(fā)揮GDI的威力。
跟貼圖相關(guān)的函數(shù)有幾個(gè):
BitBlt:最基本的塊傳輸函數(shù)。
StretchBlt:比同BitBlt,它支持圖像的拉伸和壓縮,當(dāng)不需要拉伸和壓縮時(shí)候,它的效果和BitBlt并無二致。
TransparentBlt:比同StretchBlt,它多了個(gè)“摳色”(Color Keying)功能,能把某種顏色或者某個(gè)范圍的顏色摳去而不作塊傳輸處理,以此來繪制不規(guī)則圖像。
AlphaBlend:比同StretchBlt,它支持Alpha混合,即“半透明”效果,效果比簡單的“摳色”更好。
這幾個(gè)函數(shù)是一個(gè)比一個(gè)強(qiáng),但也意味著效率一個(gè)比一個(gè)低,總體上看差不多是這樣的,運(yùn)算量越大,當(dāng)然就越慢,但測(cè)試下來發(fā)覺這其實(shí)并不絕對(duì),后面會(huì)提到。
了解了這幾個(gè)函數(shù)之后,我們開始加載一張圖片來觀察效果,我準(zhǔn)備的是一張320*320的png圖片,利用Windows Mobile 6.0提供的IImage接口來加載它,并把它轉(zhuǎn)變?yōu)槲粓D,獲得HBITMAP。加載png的代碼可以通過搜索引擎搜索“IImage用法”等關(guān)鍵詞來獲取,此處略過。
加載好圖片后,創(chuàng)建一個(gè)和設(shè)備顯示設(shè)備兼容的DC(Device Context),選入上面加載的位圖,用BitBlt繪制,代碼如下(為簡潔起見,只貼出關(guān)鍵代碼,并且不考慮資源釋放):
HDC hWndDC = GetDC(hWnd);
HDC hMemDC = CreateCompatibleDC(hWndDC);
SelectObject(hMemDC, hBitmap); //hBitmap是前面加載的圖片
BitBlt(hWndDC, 0, 0, iWidth, iHeight, hMemDC, 0, 0, SRCCOPY);
我們通過添加一些debug代碼來觀察BitBlt的執(zhí)行時(shí)間,在我的模擬器上大約是50 - 60ms,我發(fā)覺這個(gè)速度并不快,按道理說,BitBlt應(yīng)該可以在極短的時(shí)間之內(nèi)完成的(1 - 2ms),也只有這樣才能實(shí)現(xiàn)“流暢”的UI動(dòng)畫效果,否則圖一旦多起來,豈不是更慢。
我嘗試修改BitBlt的最后一個(gè)參數(shù),我發(fā)覺換成NOTSRCCOPY,速度更慢,變成了70多ms,說明運(yùn)算量更大了,這不是簡單的內(nèi)存拷貝;而當(dāng)我把最后一個(gè)參數(shù)換成BLACKNESS或者WHITENESS的時(shí)候,速度則很快,1ms-2ms即可完成,很顯然,對(duì)BitBlt來說,把目標(biāo)全部置為黑色或者白色,運(yùn)算量遠(yuǎn)少于像素傳送。在實(shí)驗(yàn)的時(shí)候把BitBlt替換為另外的幾個(gè)函數(shù),效果和預(yù)期的相差不大,如果圖像需要拉伸,則執(zhí)行得更慢一些,但如果圖像不是拉伸,而是壓縮,即縮小顯示,執(zhí)行速度居然比較快,有些意外,這是因?yàn)閴嚎s后圖像變小,需要傳輸?shù)南袼刈兩俚木壒省?
我考慮如何提高繪圖效率,經(jīng)過很多次嘗試,終于有所突破,我最后發(fā)現(xiàn):如果先把位圖存放在一個(gè)和DC兼容的位圖中,再用這個(gè)位圖對(duì)目標(biāo)設(shè)備進(jìn)行像素傳輸,速度十分理想。代碼:
HDC hWndDC = GetDC(hWnd);
HDC hMemDC = CreateCompatibleDC(hWndDC);
HDC hMemDCToLoad = CreateCompatibleDC(hWndDC);
HBITMAP hMemBmp = CreateCompatibleBitmap(hWndDC, iWidth, iHeight); // The compatible bitmap
HGDIOBJ hOldBmp = SelectObject(hMemDC, hMemBmp);
SelectObject(hMemDCToLoad, hBitmap);
BitBlt(hMemDC, 0, 0, iWidth, iHeight, hMemDCToLoad, 0, 0, SRCCOPY); //Do this in initialization
BitBlt(hWndDC, 0, 0, iWidth, iHeight, hMemDC, 0, 0, SRCCOPY); //This BitBlt's speed is very fast
第一次調(diào)用BitBlt,可以看作是初始化,我們計(jì)算第二個(gè)BitBlt的耗時(shí),只有1 - 2ms,非常不錯(cuò),經(jīng)過分析,我認(rèn)為原因應(yīng)該是這樣(不一定全對(duì),如有不妥請(qǐng)讀者指出):
只有在位圖格式完全一致的情況下,BitBlt才能執(zhí)行真正的內(nèi)存拷貝,否則是要經(jīng)過轉(zhuǎn)換的,轉(zhuǎn)換是需要消耗CPU時(shí)間的,所以慢。
那如何知道位圖的格式呢?用GetObject可以看出來:
如上圖所示,bmp是從png文件加載進(jìn)來的位圖的信息,而bmp2是用CreateCompatibleBitmap創(chuàng)建的位圖的信息,從這我們能看到,前者是24bit位圖,即一個(gè)像素用3個(gè)字節(jié)表示,而后者是16bit位圖,一個(gè)像素用兩個(gè)字節(jié)來表示,這個(gè)BitBlt執(zhí)行過程中,就需要轉(zhuǎn)換了,因此耗時(shí)。而實(shí)際上位圖的差別可能比這個(gè)還要復(fù)雜些,如果再討論設(shè)備無關(guān)位圖,那就說不完了……
總而言之,為了提高效率,我們要想方設(shè)法把加載進(jìn)來的位圖轉(zhuǎn)變?yōu)樵O(shè)備兼容位圖,繪制的時(shí)候直接BitBlt這些設(shè)備兼容位圖,來實(shí)現(xiàn)位圖的高效繪制。
前面討論的主要是BitBlt,那對(duì)于別的幾個(gè)Blt函數(shù)呢?我都嘗試過了,除了AlphaBlend之外,兼容位圖到設(shè)備的Blt速度上都有顯著的提高,而AlphaBlend則無法正常工作,因?yàn)榧嫒菸粓D不帶Alpha通道,而AlphaBlend貌似需要32bit的ARGB格式的位圖方可正常工作,這個(gè)問題我思考了好久都無解,如果哪位讀者對(duì)提高AlphaBlend的工作效率有心得,不妨跟我聯(lián)系下,我正急需這方面的技術(shù)資料。
因此,我給出這樣的結(jié)論,階段性結(jié)論:從文件(或資源)加載位圖后,把位圖轉(zhuǎn)為設(shè)備兼容位圖,這樣使得BitBlt在執(zhí)行SRCCOPY的時(shí)候直接使用內(nèi)存拷貝,速度很快,即便需要拉伸壓縮或者摳色等運(yùn)算,使用兼容位圖的速度也是相當(dāng)不錯(cuò)的,而使用AlphaBlend的時(shí)候,如果需要較高的效率,就應(yīng)從設(shè)計(jì)上避免繪制大幅位圖,改用小幅位圖,在不必要對(duì)每一幀都執(zhí)行Alpha混合的時(shí)候,就避免執(zhí)行,以免影響畫面的流暢性。 與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖
總結(jié)
以上是生活随笔為你收集整理的Windows Mobile的高效贴图的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: API Hook完全手册
- 下一篇: 如何关闭Windows XP/Vista