半透明及透明位图的实现技术

 
绘制半透明位图
 
有的时侯,我们希望显示一幅半透明的位图。也就是说我们将一幅位图 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);
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值