在 Visual C# 中从由 PixelData 组成的 Byte[] 数组创建位图图像

Creating a BitMap Image out of a Byte[] Array consisting of PixelData in Visual C#

在一个大学项目中,我和我的团队必须构建一个扫描单元。处理完扫描单元 returns 一个由 8 位灰度值组成的字节数组(高度大约 3,7k 像素,宽度大约 20k 像素,这个巨大的分辨率是必要的,所以设置 PixelData Pixelwise 是不可取的这会花很多时间)。

在网上搜索时,我在 This SO 主题中找到了答案。我试过如下实现:

public static class Extensions
{
    public static Image ImageFromArray(
    this byte[] arr, int width, int height)
    {
        var output = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);
        var rect = new Rectangle(0, 0, width, height);
        var bmpData = output.LockBits(rect,
            ImageLockMode.ReadWrite, output.PixelFormat);
        var ptr = bmpData.Scan0;
        Marshal.Copy(arr, 0, ptr, arr.Length);
        output.UnlockBits(bmpData);
        return output;
    }
}

我试过 运行 函数的数组填充如下:

        testarray[0] = 200;
        testarray[1] = 255;
        testarray[2] = 90;
        testarray[3] = 255;
        testarray[4] = 0;
        testarray[5] = 0;
        testarray[6] = 100;
        testarray[7] = 155;

并希望在图片框中显示 bmp:

pictureBox1.Image = Extensions.ImageFromArray(testarray, 2, 2);

调试时,代码通过函数运行,但结果显示错误图像。

此外,如果有人知道更简单的方法来计算任务,那么分享一下方法会非常好。我找不到方法

  1. 在 C# 中使用 8 位灰度像素格式
  2. 创建一个包含流和 PixelFormat 的位图对象

非常感谢您的帮助:)

  1. 使用 Format8bppIndexed 并设置明显的调色板

    Bitmap ImageFromArray(byte[] arr, int width, int height)
    {
        var output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
        var rect = new Rectangle(0, 0, width, height);
        var bmpData = output.LockBits(rect,ImageLockMode.WriteOnly, output.PixelFormat);
        var ptr = bmpData.Scan0;
        if (bmpData.Stride != width)
            throw new InvalidOperationException("Cant copy directly if stride mismatches width, must copy line by line");
        Marshal.Copy(arr, 0, ptr, width*height);
        output.UnlockBits(bmpData);
        var palEntries = new Color[256];
        var cp = output.Palette;
        for (int i = 0; i < 256; i++)
            cp.Entries[i] = Color.FromArgb(i, i, i);
        output.Palette = cp;            
        return output;
    }
    
  2. 将 PictureBox.SizeMode 设置为 StretchImage。你可能会需要它。