当我使用格式为 ImageFormat.Bmp 的 Bitmap.Save 方法时,我发现文件中的位图头信息在 biSizeImage 字段中为零。
据我所知,根据规格,这是可以的,但不幸的是,我被迫使用的糟糕的嵌入式设备坚持要求正确设置。
所以问题是如何在保存位图时始终设置此标头信息字段?
当我使用格式为 ImageFormat.Bmp 的 Bitmap.Save 方法时,我发现文件中的位图头信息在 biSizeImage 字段中为零。
据我所知,根据规格,这是可以的,但不幸的是,我被迫使用的糟糕的嵌入式设备坚持要求正确设置。
所以问题是如何在保存位图时始终设置此标头信息字段?
正如您所怀疑的,问题在于 0 是 RGB 位图的图像大小字段的完全允许值。该结构的MSDN 文档证实了BITMAPINFOHEADER
这一事实:
biSizeImage
图像的大小,以字节为单位。BI_RGB
对于位图,这可以设置为零。如果
biCompression
是BI_JPEG
或BI_PNG
,biSizeImage
分别表示JPEG或PNG图像缓冲区的大小。
因此,.NET Framework 中的实现只是以标准的、记录在案的方式做事。由于您需要其他东西,因此您必须自己处理保存到文件的过程,这将允许您手动修改结构的biSizeImage
成员BITMAPINFOHEADER
。
此处提供了一个非常全面的示例:将控制图像保存到位图文件。当然,它是为 Compact Framework 编写的,但大多数单独的组件仍然适用。您需要从 Windows API 中 P/Invoke 几个函数(访问www.pinvoke.net了解定义),并使用 DC。
自己动手绘图可能也会更快,因为您使用的是 GDI 子系统,而不是 GDI+。此处提供了有关该通用方法的文章:C# 中的 1bppBITMAPINFOHEADER
,它似乎也展示了使用struct将事情掌握在自己手中。
如果您了解非托管 C++ 代码,这里有一个教程可以让您了解必须在 C# 中实现什么来做同样的事情:加载和保存位图。正如您所看到的,所需的代码确实没有那么长,尽管仍然比单行Bitmap.Save
方法多。
我也遇到了这个问题,并通过一个简单的技巧解决了。保存位图,然后将其作为文件流打开并biSizeimage
手动更改字段。
picbpp.Save("pic.bmp", ImageFormat.Bmp);
string path = "pic.bmp";
FileStream fs = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.None);
// Change biSizeimage field manually.
Byte[] info = new byte[] {0x10,0x59};
fs.Seek(34, SeekOrigin.Begin);
fs.Write(info, 0, info.Length);
fs.Close();