首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

透明位圖繪製:TransparentBlt API 與手動遮罩法 (動態生成單色遮罩) 完整教學

     編輯:關於C語言

方法一:系統 API TransparentBlt (Win98/2000+)


BOOL TransparentBlt(
    HDC hdcDest, int xDest, int yDest, int wDest, int hDest,
    HDC hdcSrc,  int xSrc,  int ySrc,  int wSrc,  int hSrc,
    UINT crTransparent // 透明色 COLORREF
);
  • 需連結 Msimg32.lib,載入 Msimg32.dll。
  • Win98 有資源洩漏 Bug,生產環境不建議使用。
  • 支援縮放 (來源/目標尺寸不同)。

方法二:手動遮罩法 — 核心原理 (Raster Operations)

目標:將來源位圖中「透明色」像素**不繪製**,保留目標 DC 原有像素。
利用 **單色遮罩位圖** (1-bit per pixel) 配合 ROP 碼組合實現。

步驟詳解

  1. 建立單色遮罩位圖 (與來源同寬高):
    
    HBITMAP hMask = CreateBitmap(nWidth, nHeight, 1, 1, NULL); // 1 plane, 1 bit/pixel
    HDC hMaskDC = CreateCompatibleDC(hdcSrc);
    SelectObject(hMaskDC, hMask);
    
  2. 設定來源 DC 背景色為透明色,BitBlt 到遮罩 DC (SRCCOPY):
    
    SetBkColor(hdcSrc, crTransparent); // 透明色 → 背景色
    BitBlt(hMaskDC, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, SRCCOPY);
    // 結果:來源中透明色像素 → 遮罩變白 (1),非透明色 → 遮罩變黑 (0)
    
  3. 設定來源 DC 前景色白、背景色黑,將遮罩與來源 AND (SRCAND):
    
    SetBkColor(hdcSrc, RGB(0,0,0));
    SetTextColor(hdcSrc, RGB(255,255,255));
    BitBlt(hdcSrc, 0, 0, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
    // 結果:遮罩白(1)處保留來源像素,遮罩黑(0)處來源變黑 (0)
    // 透明區域在來源 DC 變為純黑
    
  4. 設定目標 DC 前景色黑、背景色白,將遮罩與目標 AND (SRCAND):
    
    SetBkColor(hdcDest, RGB(255,255,255));
    SetTextColor(hdcDest, RGB(0,0,0));
    BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, hMaskDC, 0, 0, SRCAND);
    // 結果:遮罩白(1)處目標變黑 (準備接收來源),遮罩黑(0)處目標保留原像素
    
  5. 將處理後來源 (透明區已黑) OR 到目標 (SRCPAINT):
    
    BitBlt(hdcDest, xDest, yDest, nWidth, nHeight, hdcSrc, 0, 0, SRCPAINT);
    // 結果:來源黑(0)不影響目標,來源非黑像素覆蓋目標黑區 → 完成透明合成
    
  6. 清理:DeleteObject(hMask), DeleteDC(hMaskDC)。

MFC 封裝函式範例


void DrawTransparentBitmap(CDC* pDestDC, CBitmap* pSrcBmp, CPoint ptDest, COLORREF crTransparent) {
    BITMAP bm; pSrcBmp->GetBitmap(&bm);
    CDC srcDC, maskDC;
    srcDC.CreateCompatibleDC(pDestDC);
    maskDC.CreateCompatibleDC(pDestDC);

    CBitmap* pOldSrc = srcDC.SelectObject(pSrcBmp);
    CBitmap maskBmp; maskBmp.CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL);
    CBitmap* pOldMask = maskDC.SelectObject(&maskBmp);

    // 1. 生成遮罩
    srcDC.SetBkColor(crTransparent);
    maskDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &srcDC, 0, 0, SRCCOPY);

    // 2. 來源 AND 遮罩 → 透明區變黑
    srcDC.SetBkColor(RGB(0,0,0)); srcDC.SetTextColor(RGB(255,255,255));
    srcDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &maskDC, 0, 0, SRCAND);

    // 3. 目標 AND 遮罩 → 透明區變黑 (準備接收)
    pDestDC->SetBkColor(RGB(255,255,255)); pDestDC->SetTextColor(RGB(0,0,0));
    pDestDC->BitBlt(ptDest.x, ptDest.y, bm.bmWidth, bm.bmHeight, &maskDC, 0, 0, SRCAND);

    // 4. 來源 OR 目標 → 完成
    pDestDC->BitBlt(ptDest.x, ptDest.y, bm.bmWidth, bm.bmHeight, &srcDC, 0, 0, SRCPAINT);

    srcDC.SelectObject(pOldSrc);
    maskDC.SelectObject(pOldMask);
}

ROP 碼邏輯真值表

操作ROP邏輯遮罩=1 (非透明)遮罩=0 (透明)
生成遮罩SRCCOPYD = SS=透明色→D=1(白) | S≠透明色→D=0(黑)—
來源預處理SRCANDD = S & M保留 SS=0 (黑)
目標預處理SRCANDD = D & MD=0 (黑) 準備接收保留 D
最終合成SRCPAINTD = S | DS 覆蓋 DD 不變

進階:Alpha Blend (32-bit 位圖含 Alpha 通道)


BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; // 全域不透明度 255, 使用逐像素 Alpha
AlphaBlend(hdcDest, x, y, w, h, hdcSrc, 0, 0, w, h, bf);
// 需 32-bit DIB Section (biBitCount=32, biCompression=BI_RGB),Alpha 通道預乘或非預乘依 bf.AlphaFormat

優點:支援半透明、漸變邊緣、陰影效果。缺點:需 32-bit 位圖、Win2000+、效能略低於遮罩法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved