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

C# 從 byte[] 建立 256 階灰階 Bitmap (含調色盤與資料對齊處理)

     編輯:關於C語言

原始灰階位元組陣列 (每像素 1 byte, 0-255) 轉為 `Format8bppIndexed` Bitmap,需處理:調色盤建立、行資料 4-byte 對齊 (DWord padding)、垂直翻轉 (BMP 由下而上儲存)。

完整實作


public static Bitmap CreateGrayscaleBitmap(byte[] pixelData, int width, int height)
{
    // 1. 建立 8bpp 空白位圖 (自動含預設調色盤)
    var bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

    // 2. 存入記憶體流取得 BMP 標頭/調色盤位移
    using (var ms = new MemoryStream())
    {
        bmp.Save(ms, ImageFormat.Bmp);
        ms.Flush();

        // 3. 計算行對齊位移
        int stride = ((width * 8 + 31) / 32) * 4; // 4-byte 對齊後的行位元組數
        int padding = stride - width;
        int dataOffset = ReadInt32(ms, 10); // BMP 檔頭第 10 位元組起為資料位移

        // 4. 重寫調色盤 (0-255 灰階)
        int paletteStart = 54; // 標準 BMP: 14+40=54
        int paletteEnd = dataOffset;
        ms.Position = paletteStart;
        for (int i = 0; i < 256; i++)
        {
            byte v = (byte)i;
            ms.Write(new byte[] { v, v, v, 0 }, 0, 4); // BGR + 保留
        }

        // 5. 準備最終像素資料 (含 padding、垂直翻轉)
        byte[] finalData = new byte[stride * height];
        for (int srcY = height - 1; srcY >= 0; srcY--)
        {
            int dstY = height - 1 - srcY;
            int srcOffset = srcY * width;
            int dstOffset = dstY * stride;
            Buffer.BlockCopy(pixelData, srcOffset, finalData, dstOffset, width);
            // padding 區域已為 0 (new byte[] 預設)
        }

        // 6. 寫入像素資料
        ms.Position = dataOffset;
        ms.Write(finalData, 0, finalData.Length);
        ms.Flush();

        // 7. 從記憶體流建立最終 Bitmap
        ms.Position = 0;
        return new Bitmap(ms);
    }
}

static int ReadInt32(MemoryStream ms, int pos)
{
    ms.Position = pos;
    byte[] buf = new byte[4];
    ms.Read(buf, 0, 4);
    return BitConverter.ToInt32(buf, 0);
}

關鍵步驟解析

  1. Format8bppIndexed:8 位元索引模式,每像素 1 byte 索引調色盤。
  2. Stride 對齊:BMP 規定每行位元組數必須為 4 的倍數。公式:`((width * bits + 31) / 32) * 4`。
  3. 調色盤重寫:預設調色盤可能非灰階,需覆寫 256 條 `BGR(0)` 入口。
  4. 垂直翻轉:BMP 檔案儲存順序為**底部行在前**,記憶體陣列通常為**頂部行在前**,複製時需反轉 Y 軸。
  5. MemoryStream 當暫存:利用 `Bitmap.Save(Stream)` 產生標準 BMP 結構,再手術修改調色盤與像素資料,最後 `new Bitmap(Stream)` 還原。

效能優化建議

  • 避免 `MemoryStream` 多次分配:可預先計算總大小 `new MemoryStream(capacity)`。
  • 大量轉換時改用 `LockBits` + `Marshal.Copy` 直接操作非受控記憶體,省去 BMP 標頭解析/重建開銷。
  • .NET 6+ 可用 `System.Drawing.Common` 替代庫 (ImageSharp/SkiaSharp) 獲得跨平台一致行為。

應用場景

  • 醫學影像 (DICOM 灰階) 轉 BMP 存檔/列印。
  • 工業相機原始資料 (Mono8) 即時顯示。
  • 熱成像、深度圖、標籤圖視覺化。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved