讨厌孙俪:绘制半透明位图以及如何画透明位图

来源:百度文库 编辑:中财网 时间:2024/05/06 19:07:35
绘制半透明位图以及如何画透明位图 发布于:软件开发网 来源:互联网 作者:佚名 时间:2009-02-26 00:01


绘制半透明位图

有的时侯,我们希望显示一幅半透明的位图。也就是说我们将一幅位图B
显示到A位图上,又希望透过B位图看到A位图的一部分图像但不是全部。比如A位
图是一幅曲线图,B是一幅提示位图,我们想在显示提示的同时看到已显示的曲
线,但不需要曲线的背景
,就需有用到半透明位图。曲线看上去就象从B位图中渗
透过来,其实半透明技术就是一种渗透技术,渗透公式我们可选用多种,在这里
我们选用(AAND0x7F)ORB。注意,白色不能产生渗透。

//参数说明:
//hDIB-位图句柄
//pPal-位图调色板
//xDest-显示位图的左上角x坐标
//yDest-显示位图的左上角y坐标
voidDrawSemiTransparentBitmap(CDC*pDC,intnXDest,intnYDest,HGLOBALhDIB,CPalette*pPal)
BITMAPINFO&bmInfo=*(LPBITMAPINFO)hDIB;
intnColors=bmInfo.bmiHeader.biClrUsed?bmInfo.bmiHeader.biClrUsed:
1<intnWidth=bmInfo.bmiHeader.biWidth;
intnHeight=bmInfo.bmiHeader.biHeight;

LPVOIDlpDIBBits=(LPVOID)(bmInfo.bmiColors nColors);
CDCmemDC;
memDC.CreateCompatibleDC(pDC);
CBitmapbmp;
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);

CDCmaskDC;
CBitmapmbm;
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实现的代码如下:
voidCDemoDlg::OnPaint()
CPaintDCdc(this);
CbitmapBmpBack,BmpA,BmpB,*pOldBack,*pOldA,*pOldB;
BmpBack.LoadBitmap(IDB_BACKGROUND);//载入背景图
BmpA.LoadBitmap(IDB_BITMAPA);//载入图A
BmpB.LoadBitmap(IDB_BITMAPB);//载入图B
CDCdcBack,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指针
UINTIDImage位图资源ID
Crect&rect指定位图在pDC中的位置
COLORREFrgbMask位图的透明色

*/
voidDrawTransparentBitmap(CDC*pDC,UINTIDImage,Crect&rect,COLORREFrgbMask)
CDCImageDC,MaskDC;
CbitmapImage,*pOldImage;
CbitmapmaskBitmap,*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);
voidCDemoDlg::OnPaint()
CPaintDCdc(this);
CbitmapBmpBack,*pOldBack,;
BmpBack.LoadBitmap(IDB_BACKGROUND);

CDCdcBack;
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);