首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# BitmapData 直接操作像素:unsafe 指針高效影像處理實戰

     編輯:關於C#

背景

Bitmap.GetPixel/SetPixel 逐像素呼叫極慢。BitmapData.LockBits 配合 unsafe 指針可直接存取記憶體,效能提升 100 倍以上。

核心範例:逐像素取補 (24bppRgb)

Bitmap src = ...; // 來源圖
int w = src.Width, h = src.Height;
Bitmap dst = new Bitmap(w, h, PixelFormat.Format24bppRgb);

BitmapData srcData = src.LockBits(new Rectangle(0,0,w,h), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
BitmapData dstData = dst.LockBits(new Rectangle(0,0,w,h), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

unsafe
{
    byte* pSrc = (byte*)srcData.Scan0.ToPointer();
    byte* pDst = (byte*)dstData.Scan0.ToPointer();

    for (int y = 0; y < h; y++)
    {
        for (int x = 0; x < w; x++)
        {
            pDst[0] = (byte)(255 - pSrc[0]); // B
            pDst[1] = (byte)(255 - pSrc[1]); // G
            pDst[2] = (byte)(255 - pSrc[2]); // R
            pSrc += 3; pDst += 3;
        }
        // 跨越 Stride 與 Width*3 的差值 (行尾填充位元組)
        pSrc += srcData.Stride - w * 3;
        pDst += dstData.Stride - w * 3;
    }
}

src.UnlockBits(srcData);
dst.UnlockBits(dstData);

關鍵概念:Stride (跨距)

  • GDI+ 要求每行位元組數為 4 的倍數 (記憶體對齊)。
  • Stride = ((Width * BitsPerPixel / 8) + 3) & ~3。
  • 例:寬 6、24bpp → 18 位元組/行 → Stride = 20 (補 2 位元組填充)。
  • 迴圈結束行時必須跳過填充位元組:p += Stride - Width * BytesPerPixel。

記憶體佈局示意

Scan0 → BGR BGR BGR ... XX | BGR BGR ... XX | ...
        ↑                ↑
      Width*3          Stride

專案設定

  • 專案屬性 → Build → **Allow unsafe code** (勾選)。
  • 或命令列編譯加 /unsafe。

進階技巧

  • 平行化:Parallel.For(0, h, y => { ... }) 多核心加速。
  • SIMD:System.Numerics.Vector 每次處理 128/256 位。
  • 快取:重複使用 BitmapData 避免頻繁 Lock/Unlock。
  • 格式選擇:Format32bppPArgb 4 位元組對齊,無填充,指標運算更簡單。

小結

掌握 LockBits + unsafe + Stride 計算,即可在 C# 實現 C/C++ 級別的高效影像處理,是電腦視覺、即時渲染的基礎技能。

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