使用LockBits从内存创建的GDI

使用LockBits从内存创建的GDI

本文介绍了使用LockBits从内存创建的GDI +通用错误保存位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我在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是该产品细分市场中的千磅大猩猩.

The GDI+ generic error when saving a bitmap is obviously a common problem according to my research here on SO and the web. Given following simplified snippet:

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");

This results in the 0x80004005 generic error. The usual reason for this are said to be locks on components, but I do not see anything here I. Am I just blind? The path I am saving to exists, of course, only a empty bmp file is created (0B).

Background: I am getting pixel data from a camera driver that I transfer to .NET using a C++/CLI wrapper, so the Bitmap object above is returned by a function call. But since this small example already fails, I guess that there is nothing wrong with the adapter.

Any suggestions are highly appreciated!

解决方案
   Bitmap bmp = new Bitmap(2048, 2048, PixelFormat.Format16bppGrayScale);

GDI+ exceptions are rather poor, you'll have little hope to diagnose the two mistakes. The lesser one is your Save() call, it doesn't specify the ImageFormat you want to save. The default is PNG, not BMP as you hoped.

But the core one is PixelFormat.Format16bppGrayScale. When GDI+ was designed, long before .NET came around, everybody was still using CRTs instead of LCD monitors. CRTs were quite good at displaying a gamut of colors. Although good, there were no mainstream CRTs yet that were capable of display 65536 distinct gray colors. Most of all restricted by the DAC in the video adapter, the chip that converts the digital pixel value to an analog signal for the CRT. A DAC that can convert with 16-bit accuracy at 100 MHz or more wasn't technologically feasible yet. Microsoft gambled on display technology improving to make that possible someday so specified Format16bppGrayScale as a pixel format that might someday be available.

That did not happen. Rather the opposite, LCDs are significantly worse at color resolution. Typical LCD panels can only resolve 6 bits of a color rather than the 8 bits available from the pixel format. Getting to 16-bit color resolution is going to require a significant technological break-through.

So they guessed wrong and, since the pixel format isn't useful, GDI+ doesn't actually have an image encoder that can write a 16bpp grayscale image format. Kaboom when you try to save it to disk, regardless of the ImageFormat you pick.

16bpp grayscale is actually used, radiological imaging uses that pixel format. With very expensive displays to make it actually useful. Such equipment however invariable uses a custom image format to go with that, DICOM is the usual choice. GDI+ doesn't have a codec for it.

You'll need to go shopping for a library that supports the image format that your customer wants. Lead Tools is the thousand pound gorilla in that product segment.

这篇关于使用LockBits从内存创建的GDI +通用错误保存位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 10:05