利用CImage類來生成精靈動畫

2021-07-23 15:46:13 字數 4635 閱讀 3707

cimage類是atl和mfc共用的乙個類,其標頭檔案為atlimage.h,主要用於jpg、png、gif等格式檔案的開啟,顯示與儲存。在vs2010(vs2010支援中文變數名)和以上版本的mfc程式設計中,不需要將標頭檔案包含進來。vc6.0、vs2008建立mfc程式要使用cimage類,必須先將標頭檔案包含進來,可以包含在當前**的cpp檔案中,也可以包含在所屬類的標頭檔案中,不過最好還是包含在工程的stdafx.h檔案中。cimage總共有39個成員函式,在我們這個精靈動畫例項裡只用到了其中幾個。

使用cimage的一般過程:

(1)、新增標頭檔案

開啟應用程式的stdafx.h檔案新增cimage類的包含檔案:

#include <atlimage.h>
(2)、載入和處理png

定義乙個cimage類物件,然後呼叫cimage::load方法裝載乙個外部影象檔案。

首先看下面這段**

cimage image;

image.load(l"d:\\使用者目錄\\pictures\\example.jpg");

image.draw(getdc()->m_hdc,crect(0,0,320,240));

cimage類支援以load方法讀取本地磁碟上的檔案,並用draw方法來顯示。其中路徑字串前面的「l」是mfc的乙個巨集,表示l修飾的字串是unicode串,是寬字元,告訴編譯器後面字串包括』/0』每個字元都用兩個位元組來儲存。

png中攜帶每畫素的顏色資訊和透明度資訊,而cimage類在繪製png時,發現當前透明度為0,則會自動將此點填充為純白色,由此,我們把畫素的alpha透明值代入計算。如果乙個畫素它的alpha分量為0,即該畫素是透明的,則該畫素的紅、綠、藍三個分量通過下面三行**會變為(0,0,0),則最終該畫素變成了(0,0,0,0)的形式,那通過前面的學習已經知道24位畫素(0,0,0)是乙個純黑色,那在我們這個例子中png中本身的不透明純黑色畫素就是(0,0,0,255),即在於後面alpha值的區別。

若是乙個全白色的畫素且該畫素不透明,通過3行**仍然會保持不變,即(255,255,255,255)。

pbits[index]=pbits[index]*pbits[index+3]/255;       //b

pbits[index+1]=pbits[index+1]*pbits[index+3]/255; //g

pbits[index+2]=pbits[index+2]*pbits[index+3]/255; //r

cimage g_transparentimg;

cimage g_opaqueimg;

bool loadimages()

//判斷源是否帶有alpha值

if (g_transparentimg.getbpp()==32)}}

return

true;

}

可以看到:

cimage::getbpp() 函式原型:int getbpp( ) return value:the number of bits

per pixel. the bits per pixel is usually 1, 4, 8, 16, 24, or 32。

cimage:: getbits () 函式原型: void* getbits( )

作用:getbits()函式讀取資料區,返回左上角畫素(原點在左上角)或左下角畫素(原點在左下角)的位址,跟內部順序有關。

cimage::getpitch 函式原型:int getpitch( )

作用:如果影象的畫素儲存順序是從上到下(也就是getbits()返回左上角畫素的位址),這時getpitch()返回乙個正值,反之為負值,大小為影象寬所占有的位元組數,例如24位800*600的,返回值應該是正或負的800*3。這樣用每一行的位元組數乘行數就可以得到起始位置了。

pbits+=(g_transparentimg.getheight()-1)*g_transparentimg.getpitch();

//該行**得到的起始位置,

``![這裡寫描述](

byte是乙個資料型別,8個位,即1個位元組,其實是無符號字元型,可以把它用在所有需要用無符號字元型的任何地方。byte是讓人關注它的長度,而不需要關注它的型別。其實一切都是byte,short 為2個byte,int 長度為4個byte。sizeof()就是獲取資料型別是幾個byte,因此在記憶體操作中都習慣使用byte作為最小儲存單位。

(2)、讀取精靈列表生成動畫

首先我們用乙個二維陣列以畫素為單位初始化了精靈列表中每張精靈幀所在png中的具體位置,

> cimage::isnull 函式原型:bool isnull( ) 若載入成功,返回false,如果當前沒有成功載入,則範圍true。

> cimage::draw 函式原型: bool draw(hdc hdestdc, int xdest, int ydest, int

> ndestwidth, int ndestheight, int xsrc, int ysrc, int nsrcwidth, int

> nsrcheight ) bool draw(hdc hdestdc, const rect& rectdest, const rect&

> rectsrc ) bool draw(hdc hdestdc, int xdest, int ydest ) bool

> draw(hdc hdestdc, const point& pointdest ) bool draw(hdc hdestdc,int

> xdest, int ydest, int ndestwidth, int ndestheight) bool draw(hdc

> hdestdc, const rect& rectdest ) 其中,hdestdc用來指定繪製的目標裝置環境控制代碼,(xdest,

> ydest)和pointdest用來指定影象顯示的位置,這個位置和源影象的左上角點相對應。ndestwidth和ndestheight分別指定影象要顯示的高度和寬度,xsrc、ysrc、nsrcwidth和nsrcheight用來指定要顯示的源影象的某個部分所在的位置和大小。rectdest和rectsrc分別用來指定目標裝置環境上和源影象所要顯示的某個部分的位置和大小。

需要說明的是,draw方法綜合了stretchblt()、transparentblt()和alphablend()函式的功能。預設時,draw的功能和stretchblt()相同。但當影象含有透明色或alpha通道時,它的功能又和transparentblt、alphablend相同。因此,在一般情況下,我們都應該盡量呼叫cimage::draw方法來繪製影象。通過追蹤除錯,可得知本例的cimage在繪製透明影象時,底層最終會呼叫alphablend()函式,而alphablend()函式執行的融合操作為:

dst.rgb = src.alpha * src.rgb + (1 - src.alpha) * dst.rgb

即目標畫素=源畫素+(1-源畫素alpha值)*目標畫素值

則乙個透明度為0的(0,0,0,0)的畫素與乙個目標畫素為(0.5,0.2,0.1)融合結果為(0.5,0.2,0.1),即目標畫素保持不變,實現了透明效果。黑色畫素(0,0,0,1)與該畫素(0,0,0,1),即黑色畫素實現了它的完全不透明效果,將會覆蓋在目標畫素之上。如果黑色畫素透明度為0.5,則最終結果畫素會是源畫素和目標畫素各50%的合成。

g_ transparentimg .draw(hdc,x,y,240,314,

frames[findex][0],

frames[findex][1],

240,314);//繪製

該draw()函式根據當前findex的值去讀取精靈列表中22幀的其中一幀來繪製到當前的裝置上下文中。
while( msg.message!=wm_quit )

else }

「`上面的**表示,只要程式沒有退出,每次程式重新整理螢幕視窗,就會呼叫一次自定義函式drawimages(),上面的**drawimages()也顯示它是呼叫draw()函式來實現最終的繪圖操作的,這就相當於每次程式更新螢幕視窗時,draw()函式就得以執行一次,索引值findex也加一,即進一步讀取下一幀。當讀取到精靈列表最後一幀時,則將精靈幀索引值重置為0,表示要從精靈列表的第一張重新開始讀起,如此不斷重複迴圈,就實現了精靈動畫效果。

drawimages()中的tpre = gettickcount();是獲得作業系統啟動到執行這個函式時的毫秒值,而在_twinmain()裡我們還執行了一次這個函式,如果兩次執行這個函式的時間差為100毫秒,才執行drawimages()函式,這就實現了延時控速。

利用註解來生成HELLO WORLD

web.xml檔案 springmvc org.springframework.web.servlet.dispatcherservlet contextconfiglocation classpath springmvc.xml 1 do處理器實現類 package controller impo...

利用word vb巨集來生成sql

昨天boss下了個命令讓我用word巨集的方式來快速生成sql,這樣在我們建表的時候就不用在一條一條元資料的輸入。從而提高效率節約成本 這裡的vb巨集要針對固定的資料庫資料字典 進行的。由於 太長就不拿出來了,這裡是word中的 式和vb執行後的結果如下 檔名稱 t test 中文描述 使用者資訊表...

利用LSTM來生成文字 程式碼詳解(部分)

coding utf 8 time 2019 9 119 44 author superxjz func lstm 匯入實驗所需要的各種工具包 import numpy from keras.models import sequential from keras.layers import dens...