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

C# 數位影像處理三大核心技法:像素提取、記憶體複製、指標操作完整對比

     編輯:關於C#

以 **24 位彩色轉灰階** 為例,系統對比 C# 三大影像處理技法:**GetPixel/SetPixel(像素提取)**、**LockBits + Marshal.Copy(記憶體複製)**、**LockBits + unsafe 指標(指標操作)**,並給出完整代碼與性能特徵分析。

灰階轉換公式

  • 標準加權:Gray = 0.299*R + 0.587*G + 0.114*B(符合人眼亮度感知)
  • 簡化版:Gray = G(綠色權重最高,極速近似)

技法一:像素提取法 —— 最直觀、最慢

if (bitmap != null) {
    var newBmp = bitmap.Clone() as Bitmap;
    for (int x = 0; x < newBmp.Width; x++) {
        for (int y = 0; y < newBmp.Height; y++) {
            Color px = newBmp.GetPixel(x, y);
            int gray = (int)(px.R * 0.299 + px.G * 0.587 + px.B * 0.114);
            newBmp.SetPixel(x, y, Color.FromArgb(gray, gray, gray));
        }
    }
    pictureBox1.Image = newBmp.Clone() as Image;
}
  • 優點:代碼可讀性最高,適合教學、小圖原型。
  • 缺點:每次呼叫皆涉及非託管轉換與邊界檢查,**性能極差**(O(n) 乘以巨大常數)。

技法二:記憶體複製法 —— 生產環境標準選擇

if (bitmap != null) {
    var newBmp = bitmap.Clone() as Bitmap;
    var rect = new Rectangle(0, 0, newBmp.Width, newBmp.Height);
    var bmpData = newBmp.LockBits(rect, ImageLockMode.ReadWrite, newBmp.PixelFormat);
    IntPtr ptr = bmpData.Scan0;
    int bytes = newBmp.Width * newBmp.Height * 3;  // 24bpp = 3 bytes/px
    byte[] rgb = new byte[bytes];
    Marshal.Copy(ptr, rgb, 0, bytes);  // 非託管→託管陣列

    for (int i = 0; i < rgb.Length; i += 3) {
        double gray = rgb[i+2]*0.299 + rgb[i+1]*0.587 + rgb[i]*0.114; // BGR 順序
        byte g = (byte)gray;
        rgb[i] = rgb[i+1] = rgb[i+2] = g;
    }

    Marshal.Copy(rgb, 0, ptr, bytes);  // 託管→非託管
    newBmp.UnlockBits(bmpData);
    pictureBox1.Image = newBmp.Clone() as Image;
}
  • 核心:**LockBits 鎖定記憶體 → Marshal.Copy 雙向傳輸 → 陣列運算 → UnlockBits**。
  • 優點:將像素運算移至託管陣列,**速度提升 50-100 倍**,安全、無需 unsafe 上下文。
  • 注意:PixelFormat.Format24bppRgb 記憶體佈局為 **BGR** 順序(非 RGB),Stride 可能大於 Width*3(記憶體對齊),實際處理時應用 bmpData.Stride 計算行偏移。

技法三:指標操作法 —— 極致性能、需 unsafe

// 需專案屬性 → Build → Allow unsafe code
unsafe {
    var bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    byte* ptr = (byte*)bmpData.Scan0.ToPointer();
    int width = bmpData.Width, height = bmpData.Height, stride = bmpData.Stride;

    for (int y = 0; y < height; y++) {
        byte* row = ptr + y * stride;
        for (int x = 0; x < width; x++) {
            byte b = row[x*3], g = row[x*3+1], r = row[x*3+2];
            byte gray = (byte)(r*0.299 + g*0.587 + b*0.114);
            row[x*3] = row[x*3+1] = row[x*3+2] = gray;
        }
    }
    bmp.UnlockBits(bmpData);
}
  • 直接操作非託管記憶體指標,**零拷貝、零邊界檢查、向量化友善**,性能再提升 2-5 倍。
  • 缺點:需 unsafe、/unsafe 編譯選項、高權限、GC 不掃描指針區域(需手動固定或用 fixed)。

性能與選型總結

技法相對速度安全性適用場景
GetPixel/SetPixel1x (基準)完全安全教學、原型、極小圖片(<100x100)
Marshal.Copy 陣列50-100x安全**生產環境首選**、中大型圖片、批次處理
unsafe 指標100-500x需謹慎高性能即時處理、視訊幀、大量並發

**建議**:預設使用 **技法二(記憶體複製法)**,兼顧性能、安全與可維護性;僅在經證實為瓶頸且環境允許時升級至技法三。

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