C# 生成16位灰度位图数据并保存到文件

C# 生成16位灰度位图数据并保存到文件,c#,bitmap,C#,Bitmap,我试图用C#从随机数据生成16位灰度位图,但它在Marshal.Copy上崩溃了 这是我的密码: Bitmap b16bpp; private void GenerateDummy16bitImage() { b16bpp = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale); var rect =

我试图用C#从随机数据生成16位灰度位图,但它在Marshal.Copy上崩溃了

这是我的密码:

   Bitmap b16bpp;
    private void GenerateDummy16bitImage()
    {

        b16bpp = new Bitmap(IMAGE_WIDTH, IMAGE_HEIGHT, System.Drawing.Imaging.PixelFormat.Format16bppGrayScale);

        var rect = new Rectangle(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
        var bitmapData = b16bpp.LockBits(rect, ImageLockMode.WriteOnly, b16bpp.PixelFormat);
        // Calculate the number of bytes required and allocate them.
        var numberOfBytes = bitmapData.Stride * IMAGE_HEIGHT * 2;
        var bitmapBytes = new short[numberOfBytes];
        // Fill the bitmap bytes with random data.
        var random = new Random();
        for (int x = 0; x < IMAGE_WIDTH; x++)
        {
            for (int y = 0; y < IMAGE_HEIGHT; y++)
            {

                var i = ((y * IMAGE_WIDTH) + x) * 2; // 16bpp

                // Generate the next random pixel color value.
                var value = (short)random.Next(5);

                bitmapBytes[i] = value;         // BLUE
                bitmapBytes[i + 1] = value;     // GREEN
                bitmapBytes[i + 2] = value;     // RED
              //  bitmapBytes[i + 3] = 0xFF;      // ALPHA
            }
        }
        // Copy the randomized bits to the bitmap pointer.
        var ptr = bitmapData.Scan0;
        Marshal.Copy(bitmapBytes, 0, ptr, numberOfBytes);//crashes here

        // Unlock the bitmap, we're all done.
        b16bpp.UnlockBits(bitmapData);

        b16bpp.Save("random.bmp", ImageFormat.Bmp);
        Debug.WriteLine("saved");
    }
位图b16bpp;
私有void generatedummy16bitmage()
{
b16bpp=新位图(图像宽度、图像高度、系统、绘图、成像、像素格式、格式16bppgrayscale);
var rect=新矩形(0,0,图像宽度,图像高度);
var bitmapData=b16bpp.LockBits(rect,ImageLockMode.WriteOnly,b16bpp.PixelFormat);
//计算所需的字节数并分配它们。
var numberOfBytes=位图数据。步长*图像高度*2;
var bitmapBytes=新短[numberOfBytes];
//用随机数据填充位图字节。
var random=新的random();
对于(int x=0;x
例外情况是:

mscorlib.dll中发生“System.AccessViolationException”类型的未处理异常

这不是我的代码。我在32位位图中找到了它并进行了修改。但我想我错过了一些东西,因为我对C#还很陌生


基本上,我所需要的只是将一系列的短片包装到位图数据中。

我已经纠正了您的一些错误(大部分是错误的大小)。但是它仍然会在
b16bpp.Save()
上崩溃,因为

位图b16bpp;
私有void generatedummy16bitmage()
{
b16bpp=新位图(图像宽度、图像高度、系统、绘图、成像、像素格式、格式16bppgrayscale);
var rect=新矩形(0,0,图像宽度,图像高度);
var bitmapData=b16bpp.LockBits(rect,ImageLockMode.WriteOnly,b16bpp.PixelFormat);
//计算所需的字节数并分配它们。
var numberOfBytes=位图数据。步长*图像高度;
var bitmapBytes=新短[图像宽度*图像高度];
//用随机数据填充位图字节。
var random=新的random();
对于(int x=0;x
我的更改说明:

  • bitmapData.Stride
    已经是
    IMAGE\u WIDTH*bytesperpoixel
    所以不需要乘以2
  • 正如您声明的
    bitmappbytes
    short[]
    一样,图像的大小必须以像素为单位,而不是以字节为单位
  • 这意味着您也不需要将
    i
    乘以2
  • 因为您有一个灰度图像,所以它没有蓝色、绿色和红色通道,只有一个16位的灰色通道
  • Copy的长度以“数组单位”为单位,而不是以字节为单位

总之,您尝试将一个数组复制到位图中8倍大。

这适用于System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:

    private static void SaveBmp(Bitmap bmp, string path)
    {
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

        BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

        var pixelFormats = ConvertBmpPixelFormat(bmp.PixelFormat);

        BitmapSource source = BitmapSource.Create(bmp.Width,
                                                  bmp.Height,
                                                  bmp.HorizontalResolution,
                                                  bmp.VerticalResolution,
                                                  pixelFormats,
                                                  null,
                                                  bitmapData.Scan0,
                                                  bitmapData.Stride * bmp.Height,
                                                  bitmapData.Stride);

        bmp.UnlockBits(bitmapData);


        FileStream stream = new FileStream(path, FileMode.Create);

        TiffBitmapEncoder encoder = new TiffBitmapEncoder();

        encoder.Compression = TiffCompressOption.Zip;
        encoder.Frames.Add(BitmapFrame.Create(source));
        encoder.Save(stream);

        stream.Close();
    }

    private static System.Windows.Media.PixelFormat ConvertBmpPixelFormat(System.Drawing.Imaging.PixelFormat pixelformat)
    {
        System.Windows.Media.PixelFormat pixelFormats = System.Windows.Media.PixelFormats.Default;

        switch (pixelformat)
        {
            case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
                pixelFormats = PixelFormats.Bgr32;
                break;

            case System.Drawing.Imaging.PixelFormat.Format8bppIndexed:
                pixelFormats = PixelFormats.Gray8;
                break;

            case System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:
                pixelFormats = PixelFormats.Gray16;
                break;
        }

        return pixelFormats;
    }

你能详细说明一下“它崩溃了”吗?不是说它会导致崩溃,而是说
Format16bppGrayScale
意味着每个像素没有单独的RGB分量,只有一个16位的值(使用
UInt16
而不是有符号的
short
类型)@Dai如果我按照你的建议去做的话。复制函数,因为它不能处理Int16[],所以参数错误。顺便说一句,我不理解那些投票结束这个问题的家伙。这有什么问题吗???我在网上搜索了2-3个小时才找到解决方案,但一个也没有找到。你搜索了多长时间与你的问题有多好无关。我投票关闭,因为(当时)你没有给我们任何细节,除了“它崩溃了,这是我的代码”。事实上,“保存到文件”部分是为了调试:)我真的需要在应用程序中使用位图。感谢你的帮助。谢谢。这个答案需要更多的认可。搜索了几个小时后,我终于找到了一个答案,可以在不需要外部库的情况下保存16bpp灰度图像,而且他们只有一票。请注意,这需要导入
PresentationCore
。顺便说一句,Format32bppArgb的翻译是不正确的。Bgr32是一种没有alpha的格式。这正是我所需要的。如广告所示,开箱即用。我绝对同意这需要提高。
    private static void SaveBmp(Bitmap bmp, string path)
    {
        Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

        BitmapData bitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

        var pixelFormats = ConvertBmpPixelFormat(bmp.PixelFormat);

        BitmapSource source = BitmapSource.Create(bmp.Width,
                                                  bmp.Height,
                                                  bmp.HorizontalResolution,
                                                  bmp.VerticalResolution,
                                                  pixelFormats,
                                                  null,
                                                  bitmapData.Scan0,
                                                  bitmapData.Stride * bmp.Height,
                                                  bitmapData.Stride);

        bmp.UnlockBits(bitmapData);


        FileStream stream = new FileStream(path, FileMode.Create);

        TiffBitmapEncoder encoder = new TiffBitmapEncoder();

        encoder.Compression = TiffCompressOption.Zip;
        encoder.Frames.Add(BitmapFrame.Create(source));
        encoder.Save(stream);

        stream.Close();
    }

    private static System.Windows.Media.PixelFormat ConvertBmpPixelFormat(System.Drawing.Imaging.PixelFormat pixelformat)
    {
        System.Windows.Media.PixelFormat pixelFormats = System.Windows.Media.PixelFormats.Default;

        switch (pixelformat)
        {
            case System.Drawing.Imaging.PixelFormat.Format32bppArgb:
                pixelFormats = PixelFormats.Bgr32;
                break;

            case System.Drawing.Imaging.PixelFormat.Format8bppIndexed:
                pixelFormats = PixelFormats.Gray8;
                break;

            case System.Drawing.Imaging.PixelFormat.Format16bppGrayScale:
                pixelFormats = PixelFormats.Gray16;
                break;
        }

        return pixelFormats;
    }