本文修正並完善「多層圖像合成」範例,詳細說明以單色 Mask 遮罩配合 SRCAND、SRCPAINT 光柵運算,將前景圖透明疊加至背景圖的完整流程,附關鍵程式碼與中間結果圖解。
BitBlt 複製至單色 DC → 系統自動將背景色轉白(1)、其餘轉黑(0)。SRCAND → 背景變黑、前景保留。SRCAND → 前景區域變黑、背景保留。SRCPAINT(OR)前景 DC → 完成透明疊加。IDB_BK(背景)、IDB_FORE(前景,含單一背景色)。CBitmap m_bmpBk, m_bmpFore; CDC m_dcBk, m_dcFore;m_bmpBk.LoadBitmap(IDB_BK);
m_bmpFore.LoadBitmap(IDB_FORE);
CClientDC dc(this);
m_dcBk.CreateCompatibleDC(&dc);
m_dcFore.CreateCompatibleDC(&dc);
void CTestSelDrawPicView::OnDraw(CDC* pDC)
{
CBitmap* pOldBk = m_dcBk.SelectObject(&m_bmpBk);
CBitmap* pOldFore = m_dcFore.SelectObject(&m_bmpFore);
CRect rect; GetClientRect(&rect);
// 1. 建立單色 Mask DC
CDC maskDC; CBitmap maskBmp;
maskDC.CreateCompatibleDC(pDC);
maskBmp.CreateBitmap(rect.Width(), rect.Height(), 1, 1, NULL);
CBitmap* pOldMask = maskDC.SelectObject(&maskBmp);
// 2. 取前景圖左上角(2,2)顏色作透明色
COLORREF clrTrans = m_dcFore.GetPixel(2, 2);
COLORREF clrSave = m_dcFore.SetBkColor(clrTrans);
// 3. 前景圖複製到 Mask → 得到二值遮罩
maskDC.BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcFore, 0, 0, SRCCOPY);
// 4. 前景圖與 Mask AND → 去背
m_dcFore.SetBkColor(RGB(0,0,0));
m_dcFore.SetTextColor(RGB(255,255,255));
m_dcFore.BitBlt(0, 0, rect.Width(), rect.Height(), &maskDC, 0, 0, SRCAND);
// 5. 背景圖與 Mask AND → 留洞
m_dcBk.SetBkColor(RGB(255,255,255));
m_dcBk.SetTextColor(RGB(0,0,0));
m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), &maskDC, 0, 0, SRCAND);
// 6. 背景 OR 前景 → 合成
m_dcBk.BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &m_dcFore, 0, 0, SRCPAINT);
// 7. 輸出到螢幕
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk, 0, 0, SRCCOPY);
// 還原物件
maskDC.SelectObject(pOldMask);
m_dcBk.SelectObject(pOldBk);
m_dcFore.SelectObject(pOldFore);
}
文中附四張關鍵截圖:
① 原始前景圖 → ② Mask 遮罩(白=透明區) → ③ 前景去背後(背景變黑) → ④ 背景留洞後(前景區變黑) → ⑤ 最終合成圖。
| API | 用途 |
|---|---|
CreateBitmap(...,1,1,NULL) | 建立 1-bit 單色點陣圖 |
SetBkColor | 設定 DC 背景色(彩色→單色轉換基準) |
SetTextColor | 設定 DC 前景色(單色→彩色轉換基準) |
BitBlt(...,SRCAND) | 邏輯 AND 運算 |
BitBlt(...,SRCPAINT) | 邏輯 OR 運算 |
此技術廣泛應用於遊戲精靈渲染、UI 圖示透明繪製、報表浮水印等場合,掌握光柵運算組合即可實現高效無 Alpha 通道的透明合成。