c - 在 C 中加载 8bpp 灰度 BMP

标签 c windows image bmp

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

例如,我只是想将这个 BMP 文件加载到内存中(640x480 8bpp 灰度),然后将它写回另一个文件。据我了解,有两个不同的 header 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);

最佳答案

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

正如 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 Struct) 不是“alpha channel ”,它只是“保留”的东西。请参阅 RGBQUAD ( MSDN, RGBQUAD) 上的 MSDN。

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

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

关于c - 在 C 中加载 8bpp 灰度 BMP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10792618/

相关文章:

jquery - 更改部分图像来源

Javascript 如果 url 然后图像

c - GCC 内联 SSE 代码

windows - git被阻塞,如何安装npm模块

c - GCC __attribute__ ((对齐 (8))) 不起作用

c++ - Win32 在代码中更改菜单

windows - 如何编写批处理文件以从源复制到目标

wpf - 如果 ImageSource 引用了无法访问的 URL,如何防止 WPF 图像被阻塞?

c - 单线程程序是否在多个线程上执行? [C]

c - 声明一个带有变量的数组