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

C# 圖片灰度化處理:BitmapData Stride 導致圖像畸變的正確解決方法

     編輯:程式設計綜合問答

問題現象

使用 LockBits 直接操作像素數據進行灰度轉換,結果圖像出現條紋、錯位、顏色錯亂。

根本原因

BitmapData.Stride(跨度/行寬)不等於 Width * BytesPerPixel。Windows 為了內存對齊,要求每行數據大小為 4 字節倍數。例如:

  • 寬度 512,24bpp (3 bytes/pixel) → 理論行大小 1536,已是 4 的倍數,Stride=1536。
  • 寬度 513 → 理論 1539,實際 Stride=1540(補齊 1 字節填充)。

代碼中按 Width * Height * 3 分配緩衝區並連續讀寫,忽略了行尾填充字節,導致後續行數據偏移。

正確處理邏輯

BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, bmp.PixelFormat);
int stride = bmpData.Stride;  // 必須使用實際 Stride
IntPtr ptr = bmpData.Scan0;
int bytes = stride * bmp.Height;  // 總字節數含填充
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);

for (int y = 0; y < bmp.Height; y++) {
    int rowOffset = y * stride;
    for (int x = 0; x < bmp.Width; x++) {
        int idx = rowOffset + x * 3;  // 24bpp: BGR 順序
        byte b = rgbValues[idx];
        byte g = rgbValues[idx + 1];
        byte r = rgbValues[idx + 2];
        byte gray = (byte)(r * 0.299 + g * 0.587 + b * 0.114);
        rgbValues[idx] = rgbValues[idx + 1] = rgbValues[idx + 2] = gray;
    }
}

Marshal.Copy(rgbValues, 0, ptr, bytes);
bmp.UnlockBits(bmpData);

關鍵點總結

  • 使用 bmpData.Stride 而非自行計算行寬。
  • 雙重循環按行處理,行內按像素步進。
  • 注意像素格式:PixelFormat.Format24bppRgb 為 BGR 順序;32bpp 含 Alpha 通道。
  • 灰度公式:Gray = R*0.299 + G*0.587 + B*0.114(BT.601 標準)。
原圖 畸變結果
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved