在C中加载8bpp灰度BMP

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

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

这里的代码是我使用的代码(我正在windows btw下做所有这些)。

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

“那些字节是什么,我怎么读,这是问题所在。”

这些字节是调色板(或以.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 Struct)不是“alpha通道”,它只是“保留”的内容。 请参阅RGBQUAD上的MSDN( MSDN,RGBQUAD )。

详细的格式描述可以在wikipedia页面找到: Wiki,bmp格式

SO和RGBQUAD结构之间也存在这个链接问题: 在没有其他库的情况下,用纯C / C ++编写BMP图像

正如维克托在他的回答中所说的那样,那些东西就是货盘。 至于你应该如何阅读它们,请看这个仅包含头标的位图类 。 特别是查看ColorTable引用,了解它如何根据BMP的类型来处理ColorTable位。