8

根据我在 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 对象由函数调用返回。但是由于这个小例子已经失败了,我猜适配器没有问题。

任何建议都非常感谢!

4

2 回答 2

22
   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 是该产品领域中的一千磅重的大猩猩。

于 2013-10-31T12:42:07.417 回答
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)
于 2020-06-17T10:16:24.960 回答