解決網路常見實作問題:效能、Stride 處理、調色盤修正。使用 LockBits/UnlockBits 直接操作記憶體,避免 GetPixel/SetPixel 低效能。
public static Bitmap ToGrayBitmap(byte[] rawValues, int width, int height) {
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
int stride = bmpData.Stride;
int offset = stride - width;
IntPtr ptr = bmpData.Scan0;
int scanBytes = stride * height;
byte[] pixelValues = new byte[scanBytes];
int posScan = 0, posReal = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
pixelValues[posScan++] = rawValues[posReal++];
posScan += offset; // 跳過 Stride 補齊位元組
}
Marshal.Copy(pixelValues, 0, ptr, scanBytes);
bmp.UnlockBits(bmpData);
// 修正調色盤:偽彩 → 灰度
ColorPalette palette;
using (Bitmap tmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
palette = tmp.Palette;
for (int i = 0; i < 256; i++)
palette.Entries[i] = Color.FromArgb(i, i, i);
bmp.Palette = palette;
return bmp;
}
關鍵點:Stride 為 4 位元組倍數,需計算 offset 跳過補齊區;調色盤預設為偽彩,必須重建為灰度映射。