【Visual C++】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类
本系列文章由zhmxy555編寫,轉載請注明出處。
http://qianmo.blog.51cto.com/5127279/875711
作者:毛星云 郵箱: happylifemxy@qq.com 歡迎郵件交流編程心得
?
我們知道,Visual C++中的CBitmap類的功能簡直太弱小了,這曾經讓Visual C++在圖像處理方面的功能比較尷尬。之前筆記里面,我們采用的CBitmap配合GDI進行透明圖像的處理有些晦澀繁瑣,而且受到圖像素材的限制,可以說是有些落后,不是太實用。
為了解決這個問題,這節筆記我們將系統的學習MFC和ATL中新增一個圖像處理的類,它就是華麗而強大的CImage類。
由于本節筆記是對CImage類的一個非常系統近乎完全的介紹,我盡量讓它涵蓋到了CImage類的所有的屬性和類成員,所以
篇幅也許比以往的筆記內容都長,里面的不少內容是用到的時候才需要掌握或者查閱的,并不用強行記憶。
一,概念講解部分
1.CImage類的定位和概述
首先,我們簡單介紹一下CImage類的定位。
CImage是MFC和ATL共享的新類,它提供了增強的位圖支持,包括加載、保存和轉換JPEG,BMP,GIF,PNG圖像格式的能力。可以說是微軟意識到了CBitmap的不足,然后推出了一個CBitmap的增強版。使用CImage類,需在代碼頭部加入包含atlp_w_picpath.h文件,即添加代碼#include "atlp_w_picpath.h"。
由于CImage擁有功能強大的類成員函數的支持,它便具有了下列四個比較出彩的特性:
1、AlphaBlend支持像素級的顏色混合,從而實現透明和半透明的效果。
2、PlgBlt能使一個矩形區域的位圖映射到一個平行四邊形區域中,而且還可能使用位屏蔽操作。
3、TransparentBlt在目標區域中產生透明圖像
4、MaskBlt在目標區域中產生源位圖與屏蔽位圖合成的效果。
2.以CImage類做媒,讓CBitmap類也能處理豐富的圖片格式
解決的思路比較明朗,我們采用CImage類的Load函數加載圖片,之后用Detch取得HBITMAP的句柄,然后再將此句柄附加給CBitmap的對象就行了。
這樣就實現了讓CBitmap類也可以操作JPG/JPEG/GIF/PNG格式的圖片。
具體代碼如下:
然后就可以用CBitmap進行余下的操作了。
3.CImage額外的一些性質
CImage類對于DIB(device-independent bitmap)設備無關位圖文件和非DIB都可以處理。我們可以通過Create函數或者CImage::Load來處理DIB部分,用Attach函數來將非DIB部分附加到一個CImage對象上。
對于以下函數,只支持DIB部分的位圖文件,他們是:
GetBitsGetColorTable,GetMaxColorTableEntries,GetPitch,GetPixelAddress,IsIndexed,SetColorTable。
我們可以通過CImage類中的IsDIBSection()函數來幫助我們判斷一個位圖文件是否為DIB部分,其定義如下:
我們需要注意的是,CImage不能被選到一個新的CDC( class of device-context設備描述表的類),CImage會為圖像創建自己的HDC(設備描述表DC的句柄)。因為一個HBITMAP只能被選入到一個HDC中一次,也就是說這個與CImage相關的HBITMAP不能被選到一個其他的HDC中。
如果需要一個CDC,我們可以從CImage中獲取HDC,然后使用CDC::FromHandle函數。
4.CImage兼容性的說明
在CImage中,有如下兼容性的要求:
只支持Windows NT4.0以上系統的成員函數:PlgBlt,MaskBlt,AlphaBlend。
只支持Windows 2000,98以上系統的成員函數:TransparentBlt,Draw
其實由于目前都是Windows XP以上的操作系統,這個知識點了解一下就行。
5.CImage類用于貼圖的一般的使用方法
使用方法不唯一,最常用的方法如下,該方法大致分為三部分:
<1> 在源文件中添加CImage類的包含文件:
#include "atlp_w_picpath.h"
<2> 定義一個CImage類對象,然后調用CImage::Load方法裝載一個外部圖像文件。Load方法有如下兩種重載:
<3> 調用CImage::Draw方法繪制圖像。
下面重點介紹一下Draw方法。
CImage::Draw 將一個位圖文件從源設備描述表復制到當前設備描述表
該函數有如下六種重載:
在上面的Draw函數的各種重載中,對于沒有指定源矩形的版本,則整個源圖像就是默認的源矩形。對于沒有指定目的矩形尺寸的,則源圖片的尺寸就是默認的目的矩形尺寸。
需要注意的是,Draw方法綜合了StretchBlt、TransparentBlt和AlphaBlend函數的功能。。通常情況下,Draw()函數作用和StretchBlt()函數一致。但是當我們的圖像中存在透明的顏色和alpha通道的時候,Draw()函數作用和TransparentBlt()或者AlphaBlend()函數一致。所以,在一般情況下,我們都盡量調用Draw方法來繪制圖像.
6.對CImage所有類成員的介紹
我將CImage類的所有類函數按功能分為了四大類,可以更方面的了解各函數的定位和作用,也方便大家查閱:
<1>功能為創建與連接,釋放的函數
Attach 附加一個HBITMAP到CImage對象,位圖類型DIB與否都可以
Create 創建一個DIB部分的位圖,并將其附加到之前創建的CImage對象
CreateEX 創建一個DIB部分的位圖(擁有額外的參數),并將其附加到之前 創建的CImage對象
Destroy 從CImage類上分離該位圖并進行刪除
Detach 從CImage類里分離該位圖
ReleaseDC 釋放設備描述表中的數據
ReleaseGDIPlus 釋放GDI+使用的源
<2>功能為輸入與輸出的函數
GetExporterFilterString 返回系統支持的輸入文件格式類型及其描述
GetImporterFilterString 返回系統支持的輸出文件格式類型及其描述
LoadFromResource 從指定的源處加載一個圖像資源
Load 從指定文件處加載一個圖像資源
IsIndexed 判斷一個位圖顏色映射到了一個索引調色盤
IsNull 判斷一個源位圖是否被當前載入
Save 以指定的類型來保存圖像
<3>關于位圖類型與參數的函數
GetBits 返回一個指向該位圖實際像素值指針
GetBPP 返回該位圖每個像素的位
GetColorTable 返回顏色表中RGB值的范圍條目
GetDC 返回目前被選擇的設備描述表
GetExporterFilterString 返回系統支持的輸入文件格式類型及其描述
GetImporterFilterString 返回系統支持的輸出文件格式類型及其描述
GetHeight 返回當前圖像的像素高度
GetMaxColorTableEntries 返回顏色表條目中的最大值
GetPitch 返回當前圖片的間距(單位為字節),用來決定像素格式的
GetTransparentColor 返回顏色表中透明色的位置
GetWidth 返回當前圖片的寬度(單位為像素)
<4>功能為圖形繪制與位圖塊傳輸相關的函數
AlphaBlend 顯示一個半透明或者透明像素的位圖
BitBlt 從源設備描述表復制一個位圖文件到當前設備描述表
Draw 從源矩形復制一個位圖到目的矩形,該函數伸縮或者拉伸位圖來適應目標矩 形的尺寸,如果有必要,會處理Alpha值和透明顏色。
MaskBlt 用指定的掩碼和光柵操作來結合顏色數據和目的位圖
PlgBlt 執行一個從源設備描述表的矩形到目標設備描述表的平行 四邊形的塊狀位圖轉換
SetColorTabel 在DIB的顏色表中設定一系列條目的RGB顏色的值
SetPixelIndexed 設置在指定坐標處的像素(使用索調色板的索引值)。
SetPixelRGB 設置在指定坐標處的像素(使用RGB值)
SetPixel 在指定坐標處設置像素的顏色
SetTransparentColor 設置將被視為透明色的顏色的索引值(只能選取調色板中的 一種顏色)
StretchBlt 從源矩形復制一個位圖到目的矩形,如果有必要,該函數會 伸縮或者拉伸位圖來適應目標矩形的尺寸,
TransparentBlt 從源設備描述表中復制一個帶有透明色的位圖到當前設備 描述表
?
二,實例運用部分
運用CImage完成透明貼圖的一個完整實例
介紹了這么多了,下面我們依然用一個實例來鞏固本節筆記的知識。
我們知道,CImage支持透明PNG的貼圖,下面我們就運用透明PNG的貼圖,來代替之前的掩碼操作貼圖。
<第一步>
準備兩張素材圖,一張背景圖,一張需要進行透明操作的人物圖。
這次的選材就很廣了,沒有之前透明操作需要自己一定的美工功底或者美工童鞋支持的諸多限制了。
我選的兩張圖片素材如下:
背景圖 bg.bmp 640x444
人物圖 onion.bmp 130x130(呵呵,可愛的洋蔥頭~~)
<第二步>
將人物圖 onion.bmp用photoshop等圖像處理軟件進行摳圖操作,除去紅黃相間的背景圖,并將背景圖用透明圖層代替,再將圖片大小調節成85x113,用png格式輸出,效果如下:
處理好的人物圖 onion.png 85x113
<第三步>
將bg.bmp以及onion.png放到工程目錄下,并在源文件寫入代碼并運行。
該代碼和筆記六中代碼的思路基本相同,只不過,將筆記六中使用掩碼操作進行透明化處理的方式換成了png透明貼圖的方式,更加的直觀和易懂易用。
詳細注釋的源代碼如下
最后得到的效果圖如下:
我們可以改變CImage::Draw函數的參數值,讓“洋蔥頭”出現在地圖不同的地方。
通過這個實例可以發現,用CImage類進行透明貼圖,實在是方便多了。
本節筆記到這里就結束了,由于近期在做一個純flash的網站,更新速度和評論的回復都不像往常那么及時,希望大家能夠體諒。
本節筆記的源代碼請點擊這里下載: 【Visual C++】Code_Note_14
感謝一直支持【Visual C++】游戲開發筆記系列專欄的朋友們,也請大家繼續關注我的專欄,我一有時間就會把自己的學習心得,覺得比較好的知識點寫出來和大家一起分享。
精通游戲開發的路還很長很長,非常希望能和大家一起交流,共同學習,共同進步。
大家看過后覺得值得一看的話,可以頂一下這篇文章,你們的支持是我繼續寫下去的動力~
如果文章中有什么疏漏的地方,也請大家指正。也希望大家可以多留言來和我探討編程相關的問題。
最后,謝謝你們一直的支持~~~
?????????????????????????????????????????????? ——————————淺墨于2012年4月3日
The end.
?
轉載于:https://blog.51cto.com/qianmo/875711
總結
以上是生活随笔為你收集整理的【Visual C++】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP——获取上传文件的后缀名
- 下一篇: 多线程程序设计