在C中加载8bpp灰度BMP

时间:2012-05-29 03:06:16

标签: c windows image bmp

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

例如,我只是尝试将此BMP文件加载到内存(640x480 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);

2 个答案:

答案 0 :(得分:7)

“那些字节是什么,我怎么读它们,这就是问题。”

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

对于灰度,调色板很简单(我不是在谈论颜色模型和RGB - &gt;灰度转换):

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)。

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

还有关于SO的这个链接问题,RGBQUAD结构:Writing BMP image in pure c/c++ without other libraries

答案 1 :(得分:2)

正如Viktor在他的回答中所说,那些位是托盘。至于你应该如何阅读它们,看看这个header-only bitmap class。特别要看一下ColorTable对于如何处理调色板位的参考,具体取决于BMP的类型。