根据我在SO和Web上的研究,保存位图时出现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对象是通过函数调用返回的。但是由于这个小例子已经失败了,所以我猜适配器没有问题。

任何建议都将受到高度赞赏!

最佳答案

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

GDI +异常情况很差,您几乎没有希望诊断这两个错误。较小的是您的Save()调用,它没有指定要保存的ImageFormat。默认值为PNG,而不是您希望的BMP。

但核心之一是PixelFormat.Format16bppGrayScale。在设计GDI +时,很早在.NET出现之前,每个人仍在使用CRT而不是LCD监视器。 CRT非常擅长显示各种色域。尽管效果不错,但尚无主流的CRT能够显示65536种不同的灰色。大部分受视频适配器中DAC限制的芯片,该芯片将数字像素值转换为CRT的模拟信号。可以在100 MHz或更高频率下以16位精度进行转换的DAC在技术上尚不可行。微软为改善显示技术而进行了赌博,以便有朝一日能够做到这一点,因此将Format16bppGrayScale指定为可能在某一天可用的像素格式。

那没有发生。相反,LCD的彩色分辨率显着变差。典型的LCD面板只能解析6位颜色,而不能解析像素格式中的8位。达到16位彩色分辨率将需要重大的技术突破。

因此他们猜错了,并且由于像素格式没有用,因此GDI +实际上没有可编写16bpp灰度图像格式的图像编码器。尝试将Kaboom保存到磁盘时,无论选择哪种ImageFormat。

实际使用16bpp灰度,放射成像使用该像素格式。具有非常昂贵的显示器,使其真正有用。然而此类设备始终使用自定义图像格式,DICOM是通常的选择。 GDI +没有编解码器。

您需要购买支持客户所需图像格式的库。 Lead Tools是该产品类别中的千磅 gorilla 。

关于c# - 使用LockBits从内存创建的GDI +通用错误保存位图,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19704021/

10-15 09:20