用BitBlt製作透明位圖(1)

 

http://express.ruanko.com/ruanko-express_17/webpage/tech3.html
這裏寫的真不錯,要好好看幾遍,對DC認識的不清,對BitBlt認識不清的人可以收穫不少。特別是結合光柵操作碼看。
但是對中間掩碼位圖的由來不清楚,怎麼樣製作掩碼位圖呢?
http://www.pcdog.com/a/19/10/x211415.html
又發現了上面的這個地方,講到如何一幅位圖的掩碼位圖,正合我意。主要用到了CreateBitmap()創建了一幅單色的位

圖,然後將裝有源位圖的設備描述表的背景色設爲源位圖的背景色——藍色,然後將裝有源位圖的設備描述表的內容復

制到裝有源碼位圖的設備描述表中,這時掩碼位圖成了圖一,我感覺這裏的hMaskDC還要把hMaskBMP裝進去才行,這裏

應該是漏掉了。
http://www.518it.net/html/pxjc/2009/0717/762.html
這裏也講到了“"掩碼"位圖的方式是:先創建一個單色的Bitmap,裝入mask DC,然後,以"SRCCOPY"的方式將裝有位圖

的位圖設備描述表繪製(BitBlt)到mask DC上。這樣,mask DC的顯示平面中的位圖即是"掩碼"位圖。”
知道了掩碼位圖的製作過程,也算小有收穫。
不過後面講的一會“設置背景色爲黑色,前景色爲白色,將掩碼位圖(圖一)與足球位圖相"與"”,一會“設置背景色爲

白色,前景色爲黑色,將掩碼位圖(圖一)與背景進行“與”運算”倒是把我弄糊塗了。
糊塗了良久,請教了師兄,之前也是有些糊塗,對設置前景色與背景色,然後在結合光柵操作碼這一做法十分不理解,如果說把生成掩碼位圖的方式說成是一種規定,那麼與後面的“規定”似乎有矛盾的地方。
還好師兄百度了一下,找到:
http://blog.sina.com.cn/s/blog_4e6f376d01000b8p.html
中間有一個關鍵的地方,那就是單色位圖與彩圖之間的轉換的問題。
模擬透明的方法也包含基於windows的單色圖向彩色圖轉換的機制,反之亦然。Windows概念中的文本顏色(前景色)和

背景色被用來映射兩種格式的轉換。在blt操作中,當dest爲彩色圖,src爲單色圖時,在進行ROP(SRCAND,SRCAND,

SRCINVERT,SRCPAINT等),操作之前,單色圖src中的0(black)像素被轉換成dest的前景色,1(white)像素被轉化

爲dest的背景色。相反,從彩色圖向單色圖轉換時,即dest爲單色圖,src爲彩色圖時,src彩色圖中所有與其背景顏色

相同的像素變成1,與其背景不同的變爲0。
這是問題的關鍵點,有了這一點說明,之前的設置設備前景色與背景色的不解就消失了。這裏還對前景色和背景色是“

映射兩種格式的轉換”,之前對前景色和背景色的錯誤認識也得到糾正。以後還是要換角度百度。

自己準備編一個程序試一試。
http://www.pcdog.com/a/19/10/x211415.html
先參照上述源碼,利用現成的::TransparentBlt或者TransparentBlt2實現最簡單的功能。
首先新建一基於對話框的工程testtransparent,然後需要載入那兩幅圖片進工程,本來準備用抓圖軟件在網頁上抓的,

但是後來看到源碼的工程中有現成的,也省了點事。將圖片的ID改爲IDB_BKBMP,IDB_FOOTBALLBMP,然後在

CTesttransparentDlg::OnPaint()的else{}中添加:
 CBitmap m_bmpBackground;
 CBitmap m_bmpFootball;
 m_bmpBackground.LoadBitmap(IDB_BKBMP);
 m_bmpFootball.LoadBitmap(IDB_FOOTBALLBMP);

  CDialog::OnPaint();
  COLORREF crMask = RGB(0x00,0x00,0xff);
  BITMAP bm;
  m_bmpFootball.GetBitmap(&bm);
  int nWidth = bm.bmWidth;
  int nHeight = bm.bmHeight;
  CDC ImageDC;
  ImageDC.CreateCompatibleDC(&dc);
  CBitmap *pOldImageBMP = ImageDC.SelectObject(&m_bmpFootball);
  ::TransparentBlt(dc.m_hDC,50,40,nWidth,nHeight,ImageDC.m_hDC,0,0,nWidth,nHeight,crMask);
  //TransparentBlt2

(dc.m_hDC,50,40,nWidth,nHeight,ImageDC.m_hDC,0,0,nWidth,nHeight,crMask);
  ImageDC.SelectObject(pOldImageBMP);
好了,應該可以看到效果了。編譯,發現dc非法,一看,原來CPaintDC dc(this);出現在了OnPaint()的if語句內了,

將其拿到if語句的頂上就可以了。一編譯,無錯,連接,有錯,提示外來符號TransparentBlt有問題。哦,網頁中提到

要用這個現成的函數需要添加一個函數庫。比較了一下兩個工程的.cpp文件,發現少了#pragma comment( lib,

"Msimg32.lib" )。加上,編譯連接無錯,運行,效果達到。註釋::TransparentBlt行,啓用TransparentBlt2,效果也

達到。當然要啓用TransparentBlt2必須要在.cpp找個空處添加函數的實現。
好了,下面準備在OnPaint中直接實現TransparentBlt2的功能。寫了一下,還有些問題,如果時間多的話,調出來應該沒問題,可惡的是一大堆的煩心事要做。暫且閣下吧。
還有當前打開的一些網頁,有時間也要看看,先留下。
http://www.518it.net/html/pxjc/2009/0717/762_2.html
http://express.ruanko.com/ruanko-express_17/webpage/tech3.html
http://www.zjol.com.cn/node2/node195/node56935/node56938/userobject7ai24982.html
http://tech.sina.com.cn/s/2005-08-09/0849686941.shtml
http://hi.baidu.com/soulshape/blog/item/897286129f0facc5c2fd7805.html
上述最後一個降到了HBITMAP和CBitmap轉換的問題,我要是按照前面講的製作掩碼位圖的方法做,這個轉換還必須要用到。
總結一下,該功能的實現要注意幾個關鍵點,一是對設備描述表,或者說設備環境,或者說設備場景要理解透徹,二是對BitBlt這個函數要認識清楚,三是要知道用BitBlt時存在一個單色位圖和彩色位圖之間的轉換規定。

 

轉自:http://sxjj04.blog.163.com/blog/static/122592653201051711262462/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章