BMP 圖像顯示完整,但反色操作只影響部分區域(通常是左上角或條帶狀)。
void CPictureView::OnInverse() {
// ...
LONG lLineBytes = WIDTHBYTES(lWidth * 8); // 按 8 位計算行字節數
for(i=0; i
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) |
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 順序),單通道操作會導致顏色錯亂且僅部分生效。