5

我无法理解 BMP 格式,我知道它应该很简单,但不知何故我错过了一些东西。我认为它是 2 个标头,后跟定义图像的实际字节,但数字不相加。

例如,我只是试图将此 BMP 文件加载到内存中(640x480 8bpp 灰度),然后将其写回另一个文件。据我了解,有两个不同的标题 BITMAPFILEHEADER 和 BITMAPINFOHEADER。BITMAPFILEHEADER 是 14 字节,而 BITMAPINFOHEADER 是 40 字节(这取决于 BMP,我怎么能说这是另一个故事)。无论如何,BITMAPFILEHEADER 通过其参数 bfOffBits 表示位图位从偏移量 1078 开始。这意味着还有 1024 ( 1078 - (40+14) ) 个其他字节,携带更多信息。这些字节是什么,我如何读取它们,这就是问题所在。还是有更正确的方法来加载 BMP 并将其写入磁盘?

这里的参考是我使用的代码(我在 Windows 下做所有这些。)

#include <windows.h>
#include <iostream>
#include <stdio.h>


HANDLE hfile;
DWORD written;

BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;

int main()
    hfile = CreateFile("image.bmp",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
ReadFile(hfile,&bfh,sizeof(bfh),&written,NULL);

ReadFile(hfile,&bih,sizeof(bih),&written,NULL);

int imagesize = bih.biWidth * bih.biHeight;

image = (unsigned char*) malloc(imagesize);

ReadFile(hfile,image,imagesize*sizeof(char),&written,NULL);

CloseHandle(hfile);

然后我正在做完全相反的事情来写入文件,

hfile = CreateFile("imageout.bmp",GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

WriteFile(hfile,&bfh,sizeof(bfh),&written,NULL);
WriteFile(hfile,&bih,sizeof(bih),&written,NULL);
WriteFile(hfile,image,imagesize*sizeof(char),&written,NULL);

CloseHandle(hfile);

编辑---已解决

好的,所以我终于做对了,毕竟它并不复杂。正如 Viktor 所指出的,这 1024 个字节代表了调色板。

我在我的代码中添加了以下内容:

RGBQUAD palette[256];
// [...] previous declarations [...] int main() [...] then read two headers
ReadFile(hfile,palette,sizeof(palette),&written,NULL);

然后当我回信时,我添加了以下内容,

WriteFile(hfile,palette,sizeof(palette),&written,NULL);
4

2 回答 2

7

“那些字节是什么,我如何读取它们,这就是问题所在。”

正如 Retired Ninja 在评论中提到的那样,这些字节是 Palette(或 .BMP 格式术语中的 ColorTable)。基本上,它是一个表,它指定位图数据中遇到的每个 8bpp 值使用什么颜色。

对于灰度,调色板是微不足道的(我不是在谈论颜色模型和 RGB -> 灰度转换):

for(int i = 0 ; i < 256 ; i++)
{
    Palette[i].R = i;
    Palette[i].G = i;
    Palette[i].B = i;
}

但是,ColorTable 的条目中有一些填充,因此它需要 4 * 256 字节,而不是您需要的 256 * 3。ColorTable 条目中的第四个组件(RGBQUAD 结构)不是“alpha 通道”,它只是“保留”的东西。请参阅 RGBQUAD 上的 MSDN ( MSDN, RGBQUAD )。

详细的格式说明可以在维基百科页面上找到:Wiki, bmp format

在 SO with RGBQUAD structure 上还有这个链接问题:Writing BMP image in pure c/c++ without other libraries

于 2012-05-29T08:30:57.533 回答
2

正如维克托在他的回答中所说,这些位就是托盘。至于你应该如何阅读它们,看看这个仅标题的位图类。特别是查看ColorTable有关它如何处理托盘位的参考资料,具体取决于给出的 BMP 类型。

于 2012-05-29T10:58:08.677 回答