【轉載】C++ 輕鬆實現透明位圖(zhuan)

鏈接:

https://blog.csdn.net/aikker/article/details/4050888

在開發界面及棋牌遊戲過程中,需要很多鏤空的圖片,而且圖片形式一般比較固定.
所以封裝了幾種常見的鏤空方法.

1. 用於沒有掩碼圖,只有指定透明色,不進行伸縮
void DrawTransBitmap( HDC hdcDest, // 目標DC
int nXOriginDest, // 目標X偏移
int nYOriginDest, // 目標Y偏移
int nWidthDest, // 目標寬度
int nHeightDest, // 目標高度
HDC hdcSrc, // 源DC
int nXOriginSrc, // 源X起點
int nYOriginSrc, // 源Y起點
COLORREF crTransparent // 透明色,COLORREF類型
);


2. 用於沒有掩碼圖,只有指定透明色,可以進行伸縮
void DrawTransBitmap( HDC hdcDest, // 目標DC
int nXOriginDest, // 目標X偏移
int nYOriginDest, // 目標Y偏移
int nWidthDest, // 目標寬度
int nHeightDest, // 目標高度
HDC hdcSrc, // 源DC
int nXOriginSrc, // 源X起點
int nYOriginSrc, // 源Y起點
int nWidthSrc, // 源寬度
int nHeightSrc, // 源高度
COLORREF crTransparent // 透明色,COLORREF類型
);

3.指定掩碼圖,和掩碼圖屬於不同圖片
void DrawTransBitmap( HDC hdcDest, // 目標DC
int nXOriginDest, // 目標X偏移
int nYOriginDest, // 目標Y偏移
int nWidthDest, // 目標寬度
int nHeightDest, // 目標高度
HDC hdcSrc, // 源DC
HDC hdcMask, //掩碼DC
int nXOriginSrc, // 源X起點
int nYOriginSrc, // 源Y起點
COLORREF crTransparent // 透明色,COLORREF類型
);

4.指定圖片和掩碼圖同屬於一張圖片
void DrawTransBitmap(HDC hDC,
int nPosX,
int nPosY,
int nCX,
int nCY,
HBITMAP hObj
);

5.得到位圖HRGN
HRGN CreateBitmapRgn(int nWidth,int nHeight,HBITMAP hbmp,COLORREF cTrans);

以下是完整代碼
//用於沒有掩碼圖,只有指定透明色,不進行伸縮
//方法一:

void DrawTransBitmap( HDC hdcDest,      // 目標DC
                    int nXOriginDest,   // 目標X偏移
                    int nYOriginDest,   // 目標Y偏移
                    int nWidthDest,     // 目標寬度
                    int nHeightDest,    // 目標高度
                    HDC hdcSrc,         // 源DC
                    int nXOriginSrc,    // 源X起點
                    int nYOriginSrc,    // 源Y起點
                    COLORREF crTransparent  // 透明色,COLORREF類型
                    )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 創建兼容位圖
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 創建單色掩碼位圖
    HDC        hImageDC = CreateCompatibleDC(hdcDest);//臨時DC
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);//臨時掩碼DC
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);

    // 將源DC中的位圖拷貝到臨時DC中,源DC已經載入位圖
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);

    // 設置臨時DC的透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明區域爲白色,其它區域爲黑色的臨時掩碼DC的掩碼位圖
    // 位圖來自臨時DC
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

    // 生成透明區域爲黑色,其它區域保持不變的位圖
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不變,其它部分變成黑色
    SetBkColor(hdcDest,RGB(255,255,255));
    SetTextColor(hdcDest,RGB(0,0,0));
     BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // "或"運算,生成最終效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);

    // 清理、恢復   
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
}

//用於沒有掩碼圖,只有指定透明色,不進行伸縮
//方法二:

void DrawTransBitmap( HDC hdcDest,      // 目標DC
                    int nXOriginDest,   // 目標X偏移
                    int nYOriginDest,   // 目標Y偏移
                    int nWidthDest,     // 目標寬度
                    int nHeightDest,    // 目標高度
                    HDC hdcSrc,         // 源DC
                    int nXOriginSrc,    // 源X起點
                    int nYOriginSrc,    // 源Y起點
                    COLORREF crTransparent  // 透明色,COLORREF類型
                    )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 創建兼容位圖
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 創建單色掩碼位圖
    HDC        hImageDC = CreateCompatibleDC(hdcDest);//臨時DC
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);//臨時掩碼DC
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);

    // 將源DC中的位圖拷貝到臨時DC中,源DC已經載入位圖
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);

    // 設置臨時DC的透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明區域爲白色,其它區域爲黑色的臨時掩碼DC的掩碼位圖
    // 位圖來自臨時DC
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);

            
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCINVERT);
         
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCINVERT);
    // 清理、恢復   
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
}

//用於沒有掩碼圖,只有指定透明色,可以進行伸縮
//方法一:

void DrawTransBitmap( HDC hdcDest,      // 目標DC
                     int nXOriginDest,   // 目標X偏移
                     int nYOriginDest,   // 目標Y偏移
                     int nWidthDest,     // 目標寬度
                     int nHeightDest,    // 目標高度
                     HDC hdcSrc,         // 源DC
                     int nXOriginSrc,    // 源X起點
                     int nYOriginSrc,    // 源Y起點
                     int nWidthSrc,      // 源寬度
                     int nHeightSrc,     // 源高度
                     COLORREF crTransparent  // 透明色,COLORREF類型
                     )
{
    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 創建兼容位圖
    HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 創建單色掩碼位圖
    HDC        hImageDC = CreateCompatibleDC(hdcDest);
    HDC        hMaskDC = CreateCompatibleDC(hdcDest);
    hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
    hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
   
    // 將源DC中的位圖拷貝到臨時DC中
    if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
    {
        BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
    }
    else
    {
        StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest,
        hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
    }
   
    // 設置透明色
    SetBkColor(hImageDC, crTransparent);

    // 生成透明區域爲白色,其它區域爲黑色的掩碼位圖
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);
   
    // 生成透明區域爲黑色,其它區域保持不變的位圖
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

    // 透明部分保持屏幕不變,其它部分變成黑色
    SetBkColor(hdcDest,RGB(0xff,0xff,0xff));
    SetTextColor(hdcDest,RGB(0,0,0));
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
   
    // "或"運算,生成最終效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
   
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    SelectObject(hMaskDC, hOldMaskBMP);
    DeleteDC(hMaskDC);
    DeleteObject(hImageBMP);
    DeleteObject(hMaskBMP);
   
}


//用於沒有掩碼圖,只有指定透明色,可以進行伸縮
 //方法二:

void DrawTransBitmap( HDC hdcDest,      // 目標DC
                     int nXOriginDest,   // 目標X偏移
                     int nYOriginDest,   // 目標Y偏移
                     int nWidthDest,     // 目標寬度
                     int nHeightDest,    // 目標高度
                     HDC hdcSrc,         // 源DC
                     int nXOriginSrc,    // 源X起點
                     int nYOriginSrc,    // 源Y起點
                     int nWidthSrc,      // 源寬度
                     int nHeightSrc,     // 源高度
                     COLORREF crTransparent  // 透明色,COLORREF類型
                     )
{
  
      if (nWidthDest < 1) return false;
      if (nWidthSrc < 1) return false;
      if (nHeightDest < 1) return false;
      if (nHeightSrc < 1) return false;
      HDC dc = CreateCompatibleDC(NULL);
      HBITMAP bitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc,
      BITSPIXEL), NULL);
      if (bitmap == NULL)
       {
                DeleteDC(dc);   
                return false;
        }
     
    HBITMAP oldBitmap = (HBITMAP)SelectObject(dc, bitmap);
    if (!BitBlt(dc, 0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc,
                     nYOriginSrc, SRCCOPY))
    {
               SelectObject(dc, oldBitmap);
               DeleteObject(bitmap);        
         DeleteDC(dc);               
         return false;
    }
      
    HDC maskDC = CreateCompatibleDC(NULL);
     HBITMAP maskBitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL);
if (maskBitmap == NULL)
      {
          SelectObject(dc, oldBitmap);
           DeleteObject(bitmap);        
           DeleteDC(dc);               
           DeleteDC(maskDC);            
           return false;
       }
       HBITMAP oldMask =  (HBITMAP)SelectObject(maskDC, maskBitmap);
       SetBkColor(maskDC, RGB(0,0,0));
       SetTextColor(maskDC, RGB(255,255,255));
  if (!BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS))
       {
              SelectObject(maskDC, oldMask);
              DeleteObject(maskBitmap);      
              DeleteDC(maskDC);              
              SelectObject(dc, oldBitmap);   
              DeleteObject(bitmap);         
              DeleteDC(dc);                  
              return false;
       }
       SetBkColor(dc, crTransparent);
       BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT);
      SetBkColor(dc, RGB(0,0,0));
       SetTextColor(dc, RGB(255,255,255));
       BitBlt(dc, 0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND);
       HDC newMaskDC = CreateCompatibleDC(NULL);
       HBITMAP newMask;
       newMask = CreateBitmap(nWidthDest, nHeightDest, 1,
                                                  GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
  if (newMask == NULL)
       {
              SelectObject(dc, oldBitmap);
              DeleteDC(dc);
              SelectObject(maskDC, oldMask);
              DeleteDC(maskDC);
              DeleteDC(newMaskDC);
              DeleteObject(bitmap);     
              DeleteObject(maskBitmap);
              return false;
       }
       SetStretchBltMode(newMaskDC, COLORONCOLOR);
       HBITMAP oldNewMask = (HBITMAP) SelectObject(newMaskDC, newMask);
       StretchBlt(newMaskDC, 0, 0, nWidthDest, nHeightDest, maskDC, 0, 0,
                    nWidthSrc, nHeightSrc, SRCCOPY);
       SelectObject(maskDC, oldMask);
       DeleteDC(maskDC);
       DeleteObject(maskBitmap);
       HDC newImageDC = CreateCompatibleDC(NULL);
       HBITMAP newImage = CreateBitmap(nWidthDest, nHeightDest, 1,
        GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
  if (newImage == NULL)
       {
              SelectObject(dc, oldBitmap);
              DeleteDC(dc);
              DeleteDC(newMaskDC);
              DeleteObject(bitmap);     
              return false;
       }
       HBITMAP oldNewImage = (HBITMAP)SelectObject(newImageDC, newImage);
       StretchBlt(newImageDC, 0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc,
              nHeightSrc, SRCCOPY);
       SelectObject(dc, oldBitmap);
       DeleteDC(dc);
       DeleteObject(bitmap);     
       BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                          newMaskDC, 0, 0, SRCAND);
       BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                       newImageDC, 0, 0, SRCPAINT);
       SelectObject(newImageDC, oldNewImage);
       DeleteDC(newImageDC);
       SelectObject(newMaskDC, oldNewMask);
       DeleteDC(newMaskDC);
       DeleteObject(newImage);   
       DeleteObject(newMask);   
       return true;
}

指定掩碼圖,和掩碼圖屬於不同圖片

void DrawTransBitmap( HDC hdcDest,      // 目標DC
                    int nXOriginDest,   // 目標X偏移
                    int nYOriginDest,   // 目標Y偏移
                    int nWidthDest,     // 目標寬度
                    int nHeightDest,    // 目標高度
                    HDC hdcSrc,         // 源DC
                    HDC hdcMask,
                    int nXOriginSrc,    // 源X起點
                    int nYOriginSrc,    // 源Y起點
                    COLORREF crTransparent  // 透明色,COLORREF類型
                    )
{

    HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);    // 創建兼容位圖
     HDC        hImageDC = CreateCompatibleDC(hdcDest);//臨時DC
     hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);

    // 將源DC中的位圖拷貝到臨時DC中,源DC已經載入位圖
     BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
     // 設置臨時DC的透明色
    SetBkColor(hImageDC, crTransparent);
    // 生成透明區域爲黑色,其它區域保持不變的位圖
    SetBkColor(hImageDC, RGB(0,0,0));
    SetTextColor(hImageDC, RGB(255,255,255));
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcMask, 0, 0, SRCAND);
    // 透明部分保持屏幕不變,其它部分變成黑色
    SetBkColor(hdcDest,RGB(255,255,255));
    SetTextColor(hdcDest,RGB(0,0,0));
     BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hdcMask, 0, 0, SRCAND);
     // "或"運算,生成最終效果
    BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
    // 清理、恢復   
    SelectObject(hImageDC, hOldImageBMP);
    DeleteDC(hImageDC);
    DeleteObject(hImageBMP);
}

//指定圖片和掩碼圖同屬於一張圖片
void DrawTransBitmap(HDC hDC, int nPosX, int nPosY, int nCX, int nCY, HBITMAP hObj)
{
    HDC hMemDC= CreateCompatibleDC(hDC);
    HBITMAP hOldBMP=(HBITMAP)::SelectObject(hMemDC,hObj);
      BitBlt(hDC,nPosX,nPosY,nCX,nCY,    hMemDC,nCX,0,SRCAND);
    BitBlt(hDC,nPosX,nPosY,nCX,nCY,    hMemDC,0,0,SRCPAINT);
    SelectObject(hMemDC,hOldBMP);
    DeleteDC(hMemDC);

}  

HRGN CreateBitmapRgn(int nWidth,int nHeight,HBITMAP hbmp, COLORREF TransColor)
{
        HDC  hmemDC;
        //創建與傳入DC兼容的臨時DC
        hmemDC = ::CreateCompatibleDC(NULL);        
        HBITMAP hOldBmp = (HBITMAP)::SelectObject(hmemDC,hbmp);
               
        //創建總的窗體區域,初始region爲0
        HRGN hrgn;
        hrgn = ::CreateRectRgn(0,0,0,0);           
        
        int y;
        for(y=0;y<nHeight ;y++)
        {
            HRGN rgnTemp; //保存臨時region
            
            int iX = 0;
            do
            {
                //跳過透明色找到下一個非透明色的點.
                while (iX < nWidth  && ::GetPixel(hmemDC,iX, y) == TransColor)
                    iX++;
               
                //記住這個起始點
                int iLeftX = iX;
               
                //尋找下個透明色的點
                while (iX < nWidth  && ::GetPixel(hmemDC,iX, y) != TransColor)
                    ++iX;
               
                //創建一個包含起點與重點間高爲1像素的臨時“region”
                rgnTemp=::CreateRectRgn(iLeftX, y, iX, y+1);
               
                //合併到主"region".
                CombineRgn( hrgn,hrgn,rgnTemp, RGN_OR);
               
                //刪除臨時"region",否則下次創建時和出錯
                ::DeleteObject(rgnTemp);
            }while(iX <nWidth );
            iX = 0;
        }
        ::SelectObject(hmemDC,hOldBmp);
        ::DeleteDC(hmemDC);
        return hrgn;   
}

 

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