BitBlt,透明點陣圖,SRCINVERT,SRCAND
- 如果一個單色點陣圖向彩色點陣圖轉換,那么單色點陣圖為1的部分(也就是白色部分),會轉換為彩色點陣圖的背景色,單色點陣圖為0的部分(黑色部分),會轉換為彩色點陣圖的前景色。
- 對一數據做兩次異或操作,那么數據將恢復到原數據,跟沒操作一樣,透明貼圖就是運用該原理。
示例:
CBitmap btfile; btfile.LoadBitmap(IDB_BITMAP1); BITMAP btinfo; btfile.GetBitmap(&btinfo); //獲取源點陣圖的大小等信息 CClientDC dcClient(this); // 當前繪畫DC,以下表述中可能會稱之為“底圖” CDC dcImage, dcMask; // 創建兩個用於處理點陣圖的兼容記憶體DC,MSDN指出圖片處理需要在記憶體DC中進行 // dcImage 該兼容DC用於處理源彩色點陣圖,而dcMask用於生成跟源圖對應的黑白掩碼點陣圖 dcImage.CreateCompatibleDC(&dcClient); // 跟dcClient兼容 dcImage.SelectObject(&btfile); // 將源彩色點陣圖選人“源圖處理dc” dcImage.SetBkColor(RGB(255, 255, 255)); //設定背景色,也就是源點陣圖的透明色,假設為白色,我們一般做素材時,將背景做成白色的, // 在下面,生成掩碼圖時,跟背景相同的會轉換為白色,其他顏色轉換為黑色 CBitmap btSingleColor; // 聲明點陣圖對象 btSingleColor.CreateBitmap(btinfo.bmWidth, btinfo.bmHeight, 1, 1, NULL);// 設定該記憶體點陣圖的大小,並設定為單色點陣圖 dcMask.CreateCompatibleDC(&dcClient); // 跟dcClient兼容 dcMask.SelectObject(&btSingleColor); // 將黑白點陣圖選人“掩碼處理dc” dcMask.BitBlt(0, 0, btinfo.bmWidth, btinfo.bmHeight, &dcImage, 0, 0, SRCCOPY); //這裡DC之間的塊數據拷貝就用到了開頭提到的知識點,從彩色點陣圖向單色點陣圖轉換, //源點陣圖的背景圖拷到掩碼DC中後變為白色,其他則為黑色 dcClient.BitBlt(0, 0, btinfo.bmWidth, btinfo.bmHeight, &dcImage, 0, 0, SRCINVERT); // 源圖跟底圖進行異或 // SRCINVERT:這個光柵操作碼代表“異或”操作,SRCAND:代表“與”操作 // 如果對一數據做兩次異或操作,那么數據將恢復到原數據,跟沒操作一樣 // 透明點陣圖就是利用這個特性,將源點陣圖異或的方式拷貝到顯示DC兩次 // 但是異或拷貝兩次的話,那么源點陣圖將不顯示,換種說法就是整張點陣圖都被透明了 // 這可不是我們想要的結果,我們的目的只是將背景色透明,所以我們還需要在這兩次 // 異或操作中加入其他操作來實現我們想要的結果,這時候就需要上面準備的“掩碼”DC來幫忙了 dcClient.BitBlt(0, 0, btinfo.bmWidth, btinfo.bmHeight, &dcMask, 0, 0, SRCAND); // 掩碼DC內的單色點陣圖跟上面的結果進行與操作,目的是將需要透明的地方保留不變,這樣下次再次用源圖異或時 // 該部分就應為執行了兩次異或而透明了;而最終結果中需要顯示的部分,在本次掩碼與操作中, // 應當為清除為0,即黑色,這樣下次異或時,將會原封不動的顯示出來。 //掩碼DC內的單色點陣圖為1的部分,將會保留顯示DC的原圖,為0的部分將會清除對應區域為0,即為黑色 dcClient.BitBlt(0, 0, btinfo.bmWidth, btinfo.bmHeight, &dcImage, 0, 0, SRCINVERT); // 最後在上面步驟的基礎上,再次用源數據DC進行一下異或操作, // 最終的結果,需要透明的部分,源圖因為執行了兩次異或,而透明了,直接顯示底圖的圖案 // 需要顯示的部分,因為是跟0異或,將得到完全的保留。 // 異或操作:(0^1 = 1) (0^0 = 0) |