Bitmap.GetPixel/SetPixel 逐像素呼叫極慢。BitmapData.LockBits 配合 unsafe 指針可直接存取記憶體,效能提升 100 倍以上。
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 = ((Width * BitsPerPixel / 8) + 3) & ~3。p += Stride - Width * BytesPerPixel。
Scan0 → BGR BGR BGR ... XX | BGR BGR ... XX | ...
↑ ↑
Width*3 Stride
/unsafe。Parallel.For(0, h, y => { ... }) 多核心加速。System.Numerics.Vector 每次處理 128/256 位。BitmapData 避免頻繁 Lock/Unlock。Format32bppPArgb 4 位元組對齊,無填充,指標運算更簡單。掌握 LockBits + unsafe + Stride 計算,即可在 C# 實現 C/C++ 級別的高效影像處理,是電腦視覺、即時渲染的基礎技能。