当前位置: 首页 > 知识库问答 >
问题:

在C中加载8bpp灰度BMP

傅皓君
2023-03-14

我无法理解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个答案

宋勇
2023-03-14

正如维克托在他的回答中所说,这些碎片就是托盘。至于如何读取它们,请看一下这个仅标题的位图类。特别是,请参考ColorTable,了解它如何根据BMP的类型处理托盘位。

壤驷涛
2023-03-14

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

这些字节是Palette(或. BMP格式术语中的ColorTable),正如Reree Ninja在评论中提到的那样。基本上,它是一个表,用于指定位图数据中遇到的每个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)。

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

在具有RGBQUAD结构的so上也有这个相关的问题:在没有其他库的情况下用纯c/c编写BMP图像

 类似资料:
  • 我想在Javascript中加载一个16位灰度PNG(其中每个像素代表一个数字/深度值。TUM使用这种文件格式来存储深度信息) 然而,opencv读取的图像。js是RGBA 8位(——我想得到CV。CV_16UC1),这似乎是因为图像是由浏览器本身解码的,如文件所示。因此,我们得到的不是一个像素,而是一个介于0和65535(2^8-1)之间的值,而是一个介于0和255(2^8-1)之间的数字,R=

  • 我是opencv4android的新手,试图加载16位深度的灰度png图像。 我试过: 但是png被读取为8bit,值在[0,255]中。我尝试了CV_LOAD_IMAGE_ANYDEPTH标志,但还是一样。我试图创建一个alpha通道或将图像作为原始图像加载,但没有成功。 我还尝试在设备上复制图像,并使用imread读取,如下所示,希望imread能够加载16位通道: 当我检查它确实存在。返回的

  • 译者:talengu PyTorch的主要接口为Python。虽然Python有动态编程和易于迭代的优势,但在很多情况下,正是Python的这些属性会带来不利。我们经常遇到的生产环境,要满足低延迟和严格部署要求。对于生产场景而言,C 通常是首选语言,也能很方便的将其绑定到另一种语言,如Java,Rust或Go。本教程将介绍从将PyTorch训练的模型序列化表示,到C语言_加载_和_执行_的过程。

  • 对于灰度发布,这里主要讲解如何实现,我所在的公司虽然使用这个逻辑实现的. 但是由于掺杂了太多业务相关东西,比如抓包,限流,缓存,校验,sso,云化,监控告警,成为了一个运维平台. 造成无法开源,真是好可惜.做这个系统多年还是想让大家来找找茬刷刷存在感的 我想当前没有一个开源的可能也和这个原因有关,太多功能和业务相关难以抽离成纯粹组件开源. 下面先讲主要逻辑结构,请看下图 这里需要讲解下这里面几个名

  • 本文向大家介绍C#图像灰度级拉伸的方法,包括了C#图像灰度级拉伸的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#图像灰度级拉伸的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的C#程序设计有所帮助。

  • 我需要用PHP创建一个灰度图像。我说的不是调色板中有灰度值的索引图像,而是真正的灰度图像。不同之处在于PNG(颜色类型)的第26字节: (有关详细信息,请参见如何检查PNG的灰度/alpha颜色类型) 我尝试了以及但我得到的都是RGB灰度图像(颜色类型2)或带有灰度调色板的RGB调色板图像(颜色类型3)。我还尝试使用而不是初始化图像,但这只会导致调色板图像。 有没有办法使用PHP的GD函数(或PH