半透明位圖(轉)

繪製半透明位圖

有的時侯,我們希望顯示一幅半透明的位圖。也就是說我們將一幅位圖B
顯示到A位圖上,又希望透過B位圖看到A位圖的一部分圖像但不是全部。比如A位
圖是一幅曲線圖,B是一幅提示位圖,我們想在顯示提示的同時看到已顯示的曲
線,但不需要曲線的背景
,就需有用到半透明位圖。曲線看上去就象從B位圖中滲
透過來,其實半透明技術就是一種滲透技術,滲透公式我們可選用多種,在這裏
我們選用(A AND 0x7F)OR B。注意,白色不能產生滲透。

//參數說明:
//hDIB -位圖句柄
//pPal -位圖調色板
//xDest -顯示位圖的左上角x座標
//yDest -顯示位圖的左上角y座標
void DrawSemiTransparentBitmap(CDC *pDC, int nXDest, int nYDest, HGLOBAL hDIB,CPalette *pPal)
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
int nColors = bmInfo.bmiHeader.biClrUsed ? bmInfo.bmiHeader.biClrUsed :
1 << bmInfo.bmiHeader.biBitCount;
int nWidth = bmInfo.bmiHeader.biWidth;
int nHeight = bmInfo.bmiHeader.biHeight;

LPVOID lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
CDC memDC;
memDC.CreateCompatibleDC( pDC );
CBitmap bmp;
bmp.CreateCompatibleBitmap( pDC, nWidth, nHeight );
CBitmap *pOldBitmap = memDC.SelectObject( &bmp );
if( pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE&&nColors<256)
CPalette *pOldMemPalette = memDC.SelectPalette(pPal, FALSE);
memDC.RealizePalette();
::SetDIBitsToDevice(memDC.m_hDC, 0, 0, nWidth, nHeight, 0, 0, 0, nHeight, lpDIBBits, (LPBITMAPINFO)hDIB, DIB_RGB_COLORS);

CDC maskDC;
CBitmap mbm;
maskDC.CreateCompatibleDC(pDC);
mbm.CreateCompatibleBitmap(pDC, nWidth, nHeight);
maskDC.SelectObject(&mbm);
maskDC.FillSolidRect(CRect(0, 0, nWidth, nHeight), RGB(0x7F, 0x7F, 0x7F));
pDC->BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND);
pDC->BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC, 0, 0, SRCPAINT);
memDC.SelectObject(pOldBitmap);
} 

如何畫透明位圖


  畫透明位圖通常的方法是使用遮罩。所謂遮罩就是一張黑白雙色的位圖,他和
要透明的位圖是對應的,遮罩描述了位圖中需要透明的部分,透明的部分是黑色的,
而不透明的是白色的,白色的部分就是透明的部分。
假設圖A是要畫的透明位圖,圖B是遮罩,圖A上是一個大寫字母A,字母是紅色的,背
景是黑色的,圖B背景是白色的,上面有一個黑色的字母A和圖A的形狀是一樣的。
比如我們要在一張藍天白雲的背景上透明地畫圖A,就是隻把紅色的字母A畫上去。我

們可以先將圖B和背景進行與操作,再把圖B和背景進行或操作就可以了。
用VC++ MFC實現的代碼如下:
void CDemoDlg::OnPaint()
CPaintDC dc(this);
Cbitmap BmpBack,BmpA,BmpB,*pOldBack,*pOldA,*pOldB;
BmpBack.LoadBitmap(IDB_BACKGROUND); // 載入背景圖
BmpA.LoadBitmap(IDB_BITMAPA); //載入圖A
BmpB.LoadBitmap(IDB_BITMAPB); //載入圖B
CDC dcBack,dcA,dcB; //聲明三個內存DC用於畫圖
dcBack.CreateCompatibleDC(&dc);
dcA.CreateCompatibleDC(&dc);
dcB.CreateCompatibleDC(&dc); //把這三個內存DC創建成和PaintDC兼容的DC

pOldBack=dcBack.SelectObject(&BmpBack);
pOldA=dcA.SelectObject(&BmpA);
pOldB=dcB.SelectObject(&BmpB); //把三個位圖選入相應的DC
dc.BitBlt(0,0,100,100,&dcBack,0,0,SRCCOPY); //畫背景
dc.BitBlt(0,0,48,48,&dcB,0,0,SRCAND); //用與的方式畫遮罩圖B
dc.BitBlt(0,0,48,48,&dcA,0,0,SRCPAINT); //用或的方式畫遮圖A
dcBack.SelectObject(pOldBack);
dcBack.SelectObject(pOldA);
dcBack.SelectObject(pOldB); //從內存DC中刪除位圖
你會看到紅色的字母A透明地畫在背景上了。

用遮罩的方法必須事先做好遮罩,遮罩和位圖大小一樣等於多消耗一倍的資源,
比較浪費。還有一種畫透明位圖的方法,基本原理是一樣的,只是不用事先做好
遮罩,根據需要動態生成遮罩,但是要求需要透明的位圖必須指定一種透明色,
凡是這個透明色的地方則畫成透明的。
用VC++ MFC實現的代碼如下:
/*
這是一個用來畫透明位圖的函數
CDC *pDC 需要畫位圖的CDC指針
UINT IDImage 位圖資源ID
Crect &rect 指定位圖在pDC中的位置
COLORREF rgbMask 位圖的透明色

*/
void DrawTransparentBitmap(CDC *pDC, UINT IDImage,Crect &rect, COLORREF rgbMask)
CDC ImageDC,MaskDC;
Cbitmap Image,*pOldImage;
Cbitmap maskBitmap,*pOldMaskDCBitmap ;
Image.LoadBitmap(IDImage);
ImageDC.CreateCompatibleDC(pDC);
pOldImage=ImageDC.SelectObject(&Image);
MaskDC.CreateCompatibleDC(pDC);
maskBitmap.CreateBitmap( rect.Width(), rect.Height(), 1, 1, NULL );
pOldMaskDCBitmap = MaskDC.SelectObject( &maskBitmap );
ImageDC.SetBkColor(rgbMask);
MaskDC.BitBlt( 0, 0, rect.Width(), rect.Height(), &ImageDC, 0, 0, SRCCOPY );

ImageDC.SetBkColor(RGB(0,0,0));
ImageDC.SetTextColor(RGB(255,255,255));
ImageDC.BitBlt(0, 0, rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND);
pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND);
pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &ImageDC, 0, 0,SRCPAINT);
MaskDC.SelectObject(pOldMaskDCBitmap);
ImageDC.SelectObject(pOldImage);
void CDemoDlg::OnPaint()
CPaintDC dc(this);
Cbitmap BmpBack,*pOldBack,;
BmpBack.LoadBitmap(IDB_BACKGROUND);

CDC dcBack;
dcBack.CreateCompatibleDC(&dc);
pOldBack=dcBack.SelectObject(&BmpBack);
dc.BitBlt(0,0,100,100,&dcBack,0,0,SRCCOPY);
DrawTransparentBitmap(&dc,IDB_BITMAPA,Crect(0,0,48,48),RGB(192,192,0));

dcBack.SelectObject(pOldBack);

 

 

 

轉載自:

     http://qingqingfeiangel.blog.163.com/blog/static/48132888200832551438738/

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