透明镂空位图的实现

来源:互联网 发布:淘宝虚拟发货怎么设置 编辑:程序博客网 时间:2024/04/29 20:47

总的思想是,取位图与背景相交区域(不相交区域保持原样),按指定的镂空颜色和透明度逐像素计算,若位图颜色为指定镂空色,则直接取背景色,否则按指定透明度对位图色和背景色进行混合运算,最后将运算结果输出,得到透明镂空的图像。代码如下:

 

*******************************************************************************

 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为位图高

原创粉丝点击