总的思想是,取位图与背景相交区域(不相交区域保持原样),按指定的镂空颜色和透明度逐像素计算,若位图颜色为指定镂空色,则直接取背景色,否则按指定透明度对位图色和背景色进行混合运算,最后将运算结果输出,得到透明镂空的图像。代码如下:
*******************************************************************************
void DrawTransAlpha( HDC hdcBack, // 背景DC
int nXBack, // 背景图左上角X坐标
int nYBack, // 背景图左上角Y坐标
int nWidthBack, // 背景图宽度
int nHeightBack, // 背景图高度
int nXFore, // 前景图左上角X坐标
int nYFore, // 背景图左上角Y坐标
int nAlpha, // 不透明度 0~255 0为完全透明 255为完全不透明
COLORREF crTrans); //镂空色
***********************************************************************************
void DrawTransAlpha(HDC hdcBack, int nXBack,int nYBack,int nWidthBack,int nHeightBack,int nXFore,int nYFore,int nAlpha, COLORREF crTrans)
{
HDC hdcMem= CreateCompatibleDC(hdcBack); //创建兼容设备
//创建一个与背景同样大小的临时图像
RECT rBackRect={nXBack,nYBack,nWidthBack, nHeightBack};
HBITMAP hbmTmp=CreateCompatibleBitmap(hdcBack,nWidthBack,nHeightBack);
HBITMAP hbmBk=(HBITMAP)SelectObject(hdcBack,hbmTmp); //替出背景图像
RECT rForeRect={nXFore,nYFore,nXFore+m_nWidth,nYFore+m_nHeight};
RECT rTransRect,rTransRect2;
//获取前景矩形与背景矩形的交集,如不相交,则不需要进行颜色计算
if(IntersectRect(&rTransRect,&rBackRect,&rForeRect))
{
BITMAP bm,bmBk;
GetObject(m_hbm,sizeof(BITMAP),&bm);
BYTE * px = new unsigned char[bm.bmHeight*bm.bmWidthBytes]; //声明暂存数组
GetBitmapBits(m_hbm,bm.bmHeight*bm.bmWidthBytes,px); //取得源位图各像素点的 RGB 值存入 px 数组中
GetObject(hbmBk,sizeof(BITMAP),&bmBk);
BYTE * pxBk = new unsigned char[bmBk.bmHeight*bmBk.bmWidthBytes]; //声明暂存数组
GetBitmapBits(hbmBk,bmBk.bmHeight*bmBk.bmWidthBytes,pxBk); //取得源位图各像素点的 RGB 值存入 pxBk数组中
rTransRect2=rTransRect;
OffsetRect (&rTransRect2, -rForeRect.left,-rForeRect.top ) ; //偏移矩形坐标
int pb=bm.bmBitsPixel/8; //获取每像素所占字节数
int pbBk=bmBk.bmBitsPixel/8;
//dy1为背景图像素行数,dy2为前景图像素行数
//dx1为背景图像素列数,dx2为前景图像素列数
int dx1,dx2,dy1,dy2;
//循环对像素进行计算,背景和前景中需要进行计算的像素分别在各自对应的矩形rTransRect和rTransRect2的范围内循环
for(dy1=rTransRect.top,dy2=rTransRect2.top;dy1<rTransRect.bottom;dy1++,dy2++)
for(dx1=rTransRect.left,dx2=rTransRect2.left;dx1<rTransRect.right;dx1++,dx2++)
{
int nBackRGB_B=dy1*bmBk.bmWidthBytes+dx1*pbBk; //计算背景图像素起始位置
int nForeRGB_B=dy2*bm.bmWidthBytes+dx2*pb; //计算前景图像素起始位置
if( RGB(px[nForeRGB_B+2],px[nForeRGB_B+1],px[nForeRGB_B])!=crTrans)
{
pxBk[nBackRGB_B] = (px[nForeRGB_B]*nAlpha+pxBk[nBackRGB_B]*(255-nAlpha))/255; //将B色彩值乘以nAlpha并与 px 相加
pxBk[nBackRGB_B+1] =(px[nForeRGB_B+1]*nAlpha+pxBk[nBackRGB_B+1]*(255-nAlpha))/255;//将 G 色彩值乘以nAlpha并与 px 相加
pxBk[nBackRGB_B+2] = (px[nForeRGB_B+2]*nAlpha+pxBk[nBackRGB_B+2]*(255-nAlpha))/255;//将 R 色彩值乘以 nAlpha并与 px 相加
}
}
SetBitmapBits(hbmTmp,bmBk.bmHeight*bmBk.bmWidthBytes,pxBk); //设置背景图数据
HBITMAP hbmOld=(HBITMAP)SelectObject(hdcMem,hbmTmp);
BitBlt(hdcBack,0,0,rBackRect.right,rBackRect.bottom,hdcMem,0,0,SRCCOPY);
delete[] px; //删除数组
delete[] pxBk;
SelectObject(hdcMem,hbmOld);
}
DeleteObject(hbmTmp);
DeleteDC(hdcMem); //删除兼容设备
}
}
***********************************************************************
//m_hbm为位图句柄 m_nWidth为位图宽 m_nHeight为位图高