需求:將文字繪製在載入的 BMP 圖像上,合成結果另存為新 BMP 檔,並支援滑鼠拖曳文字位置。本文採用 記憶體相容 DC + 相容位圖 + SetDIBits/GetDIBits 方案,避免檔案 I/O 中介,效能優於逐像素操作。
| 函數 | 用途 |
|---|---|
SetDIBits | 將原始 DIB 緩衝區像素寫入相容位圖 |
GetDIBits | 從相容位圖讀回像素到 DIB 緩衝區 |
流程:
BITMAPINFOHEADER、像素緩衝 m_lpDIBits。CreateCompatibleDC) 與相容位圖 (CreateCompatibleBitmap,尺寸同原圖)。SetDIBits 將原圖像素寫入相容位圖。TextOut 繪製文字 (支援透明背景、陰影效果)。GetDIBits 從相容位圖讀回合成後像素緩衝。
void CreateMemObject(CDC* pDC, BITMAPINFO* lpbmi, int* pnLineChar)
{
if (!m_pMemDC) { m_pMemDC = new CDC(); m_pMemDC->CreateCompatibleDC(pDC); }
if (m_pMemBmp) { m_pMemDC->SelectObject(m_pOldBmp); delete m_pMemBmp; }
m_pMemBmp = new CBitmap();
m_pMemBmp->CreateCompatibleBitmap(pDC,
m_lpBMPHdr->biWidth, m_lpBMPHdr->biHeight);
m_pOldBmp = m_pMemDC->SelectObject(m_pMemBmp);
m_pMemDC->FillSolidRect(0, 0,
m_lpBMPHdr->biWidth, m_lpBMPHdr->biHeight, RGB(255,255,255));
// 原圖像素寫入相容位圖
SetDIBits(m_pMemDC->GetSafeHdc(), (HBITMAP)m_pMemBmp->m_hObject,
0, m_lpBMPHdr->biHeight, (LPVOID)m_lpDIBits,
(BITMAPINFO*)m_lpBMPHdr, DIB_RGB_COLORS);
}
void SetBmpText(const CString& strText, BOOL bRepaint)
{
m_strBmpText = strText;
// 重新貼上原圖 (避免文字疊加殘留)
SetDIBits(m_pMemDC->GetSafeHdc(), (HBITMAP)m_pMemBmp->m_hObject,
0, m_lpBMPHdr->biHeight, (LPVOID)m_lpDIBits,
(BITMAPINFO*)m_lpBMPHdr, DIB_RGB_COLORS);
if (m_strBmpText.GetLength() > 0) {
m_pMemDC->SetBkMode(TRANSPARENT);
// 陰影:黑色偏移 (1,1)
m_pMemDC->SetTextColor(RGB(0,0,0));
m_pMemDC->TextOut(10, 10, m_strBmpText);
// 主文字:白色
m_pMemDC->SetTextColor(RGB(255,255,255));
m_pMemMemDC->TextOut(11, 11, m_strBmpText);
}
if (bRepaint) Invalidate();
}
void SetSaveBmpPath(LPCTSTR pszPath)
{
BYTE* pTemp = new BYTE[m_dwImageSize];
ZeroMemory(pTemp, m_dwImageSize);
int nCount = GetDIBits(m_pMemDC->GetSafeHdc(),
(HBITMAP)m_pMemBmp->m_hObject, 0, m_lpBMPHdr->biHeight,
(LPVOID)pTemp, (BITMAPINFO*)m_lpBMPHdr, DIB_RGB_COLORS);
// pTemp 即為合成後像素資料,寫入檔案...
delete[] pTemp;
}

白色文字帶黑色陰影,清晰可讀,位置可滑鼠拖曳調整。
SelectObject 失效。推測與 SetDIBits 重寫像素機制衝突。改用 BitBlt 或 GDI+ 可解。GetDIBits 配合 DIB_RGB_COLORS 在 8/16-bit 格式表現異常。需依 biBitCount 分支處理調色盤。Graphics::DrawImage + DrawString) 完美支援任意格式、字型、抗鋸齒、透明度、旋轉等。BMP 檔案讀寫參考《VC 知識庫線上雜誌第 21 期》胡卓愷〈位圖檔案讀寫綜述〉。測試環境:Win2000 + VC6 + 174×218 24-bit BMP。
以 SetDIBits/GetDIBits 實作圖文合成,邏輯清晰、效能尚可,適合簡單 24-bit BMP 處理。若需專業級文字排版、多格式支援、向量文字、抗鋸齒,強烈建議遷移至 GDI+ 或 Direct2D。完整原始碼含 BMP 載入/儲存、滑鼠拖曳文字位置、合成邏輯,請下載附件參考。