首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

VC++ 圖像反色僅處理部分區域:三通道處理缺失

     編輯:程式設計綜合問答

問題現象

BMP 圖像顯示完整,但反色操作只影響部分區域(通常是左上角或條帶狀)。

代碼缺陷分析

void CPictureView::OnInverse() {
    // ...
    LONG lLineBytes = WIDTHBYTES(lWidth * 8); // 按 8 位計算行字節數
    for(i=0; i

核心錯誤

  1. 位深假設錯誤:`WIDTHBYTES(lWidth * 8)` 假設 8 位(灰度圖),但彩色圖通常是 24 位(3 通道)或 32 位
  2. 像素訪問錯誤:每像素需處理 3 字節(BGR),代碼只處理 1 字節
  3. 行字節對齊:BMP 每行 4 字節對齐,`WIDTHBYTES` 計算正確,但像素步長錯誤

正確處理 24 位彩色圖

void CPictureView::OnInverse() {
    CPictureDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    
    LPSTR lpDIBBits = (LPSTR)GlobalLock(pDoc->lpBuf);
    LONG lWidth = pDoc->bi.biWidth;
    LONG lHeight = pDoc->bi.biHeight;
    WORD bitCount = pDoc->bi.biBitCount; // 獲取實際位深
    
    if (bitCount != 24) {
        AfxMessageBox(_T("僅支持 24 位彩色圖"));
        return;
    }
    
    LONG lLineBytes = WIDTHBYTES(lWidth * bitCount); // 24 位 = 3 字節/像素
    
    for (LONG i = 0; i < lHeight; i++) {
        // 行起始指針(BMP 底部優先存儲)
        LPSTR pLine = lpDIBBits + lLineBytes * (lHeight - 1 - i);
        
        for (LONG j = 0; j < lWidth; j++) {
            LPSTR pPixel = pLine + j * 3; // 每像素 3 字節:B, G, R
            
            // 反色:255 - 原值
            pPixel[0] = 255 - pPixel[0]; // Blue
            pPixel[1] = 255 - pPixel[1]; // Green
            pPixel[2] = 255 - pPixel[2]; // Red
        }
    }
    
    GlobalUnlock(pDoc->lpBuf);
    Invalidate(FALSE); // 觸發重繪
}

關鍵點總結

項目錯誤代碼正確做法
位深獲取固定 8`bi.biBitCount`
行字節計算`WIDTHBYTES(w*8)``WIDTHBYTES(w*bitCount)`
像素步長`+ j` (1 字節)`+ j * (bitCount/8)`
通道處理單字節循環 3 通道 (BGR)

調試建議

  • 斷點檢查 `bi.biWidth`、`bi.biHeight`、`bi.biBitCount` 是否正確
  • 驗證 `lLineBytes` 計算結果(24 位圖:`(width*3+3)/4*4`)
  • 用 `GetDIBits` 獲取位圖信息對比驗證

擴展:通用像素操作模板

auto processPixel = [](BYTE* p, int channels) {
    for (int c = 0; c < channels; c++) {
        p[c] = 255 - p[c]; // 反色
    }
};

// 使用
int channels = bitCount / 8; // 3 或 4
for (LONG i = 0; i < lHeight; i++) {
    LPSTR pLine = lpDIBBits + lLineBytes * (lHeight - 1 - i);
    for (LONG j = 0; j < lWidth; j++) {
        processPixel((BYTE*)(pLine + j * channels), channels);
    }
}

總結

圖像處理必須根據實際位深計算行字節、像素步長,並處理所有通道。24 位圖每像素 3 字節(BGR 順序),單通道操作會導致顏色錯亂且僅部分生效。

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