使用LockBits从内存创建的GDI +泛型错误保存位图

时间:2013-10-31 10:29:45

标签: c# gdi+ system.drawing

根据我在SO和网站上的研究,保存位图时的GDI +一般性错误显然是一个常见问题。给出以下简化的代码段:

byte[] bytes = new byte[2048 * 2048 * 2];

for (int i = 0; i < bytes.Length; i++)
{
    // set random or constant pixel data, whatever you want
}

Bitmap bmp = new Bitmap(2048, 2048, PixelFormat.Format16bppGrayScale);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 2048, 2048), ImageLockMode.ReadWrite, bmp.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, bmpData.Scan0, 8388608);
bmp.UnlockBits(bmpData);
bmp.Save(@"name.bmp");

这会导致0x80004005一般错误。通常的原因据说是锁定组件,但我在这里看不到任何东西。我只是瞎了吗?我保存的路径存在,当然,只创建一个空的bmp文件(0B)。

背景:我从使用C ++ / CLI包装器传输到.NET的相机驱动程序获取像素数据,因此上面的Bitmap对象由函数调用返回。但是由于这个小例子已经失败,我猜这个适配器没有任何问题。

任何建议都非常感谢!

2 个答案:

答案 0 :(得分:18)

   Bitmap bmp = new Bitmap(2048, 2048, PixelFormat.Format16bppGrayScale);

GDI +异常相当差,你没有希望诊断出这两个错误。较小的一个是Save()调用,它不指定要保存的ImageFormat。默认为PNG,而不是您希望的BMP。

但核心是PixelFormat.Format16bppGrayScale。当设计GDI +时,早在.NET出现之前,每个人仍然使用CRT而不是LCD显示器。 CRT非常擅长展示各种颜色。虽然很好,但还没有能够显示65536种不同灰色的主流CRT。最重要的是视频适配器中的DAC受限制,该芯片将数字像素值转换为CRT的模拟信号。可以在100 MHz或更高频率下以16位精度进行转换的DAC在技术上尚不可行。微软在改进显示技术方面进行了改进,以便有朝一日将指定的Format16bppGrayScale指定为可能某天可用的像素格式。

那没发生。相反,相反,LCD在颜色分辨率方面明显更差。典型的LCD面板只能分辨6位颜色而不是像素格式的8位。获得16位色彩分辨率将需要重大的技术突破。

所以他们猜错了,因为像素格式没用,GDI +实际上没有可以写出16bpp灰度图像格式的图像编码器。 Kaboom,当您尝试将其保存到磁盘时,无论您选择哪个ImageFormat。

实际使用16bpp灰度,放射成像使用该像素格式。使用非常昂贵的显示器使其实际有用。这种设备不变,使用自定义图像格式,DICOM是通常的选择。 GDI +没有编解码器。

您需要购买支持客户所需图像格式的图书馆。 Lead Tools是该产品领域的千磅大猩猩。

答案 1 :(得分:0)

PixelFormat.Format32bppArgb似乎在使用GDI的Ubuntu 20上对我有用。

var bitmapdata = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);

我遇到的错误是

System.ArgumentException: 'Parameter is not valid.'
at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)
   at System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
   at System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)