C++ - 从 BMP 文件中读取每个像素的位数
Posted
技术标签:
【中文标题】C++ - 从 BMP 文件中读取每个像素的位数【英文标题】:C++ - Reading number of bits per pixel from BMP file 【发布时间】:2016-06-06 21:38:38 【问题描述】:我正在尝试获取 bmp 文件中每个像素的位数。根据***,它应该在第 28 个字节。所以读完一个文件后:
// Przejscie do bajtu pod ktorym zapisana jest liczba bitow na pixel
plik.seekg(28, ios::beg);
// Read number of bytes used per pixel
int liczbaBitow;
plik.read((char*)&liczbaBitow, 2);
cout << "liczba bitow " << liczbaBitow << endl;
但是 liczbaBitow(应该保存每个像素值的位数)是 -859045864。我不知道它是从哪里来的……我迷路了。
有什么想法吗?
【问题讨论】:
您需要显示文件的打开方式。它是使用ios::binary
标志集打开的吗?
您将两个字节放入一个未初始化的(可能是 4 个字节长)整数中。第一步尝试将liczbaBitow
初始化为零。
bitmap file format 方式太复杂了,无法编写自己的解析器。使用库,可以是内置在您的平台中的库,也可以是第 3 方库。
【参考方案1】:
为了澄清@TheBluefish 的答案,这段代码有错误
// Read number of bytes used per pixel
int liczbaBitow;
plik.read((char*)&liczbaBitow, 2);
当您使用(char*)&libczbaBitow
时,您将获取一个 4 字节整数的地址,并告诉代码将 2 个字节放在那里。
该整数的其他两个字节未指定且未初始化。在这种情况下,它们是0xCC
,因为这是系统使用的堆栈初始化值。
但是,如果您从另一个函数或重复调用此函数,则可以预期堆栈中包含其他虚假值。
如果你初始化变量,你会得到你期望的值。
但是还有另一个错误.. 字节顺序在这里也很重要。此代码假设机器本机字节顺序与文件规范中的字节顺序完全匹配。有许多不同的位图格式,但根据您的参考,***文章说:
所有整数值都以 little-endian 格式存储(即最低有效字节在前)。
这和你的一样,显然也是x86 little endian。其他字段未定义为小端,因此当您继续解码图像时,您必须注意它。
理想情况下,您应该读入一个字节数组并将字节放在它们所属的位置。 见Convert Little Endian to Big Endian
int libczbaBitow;
unsigned char bpp[2];
plik.read(bpp, 2);
libczbaBitow = bpp[0] | (bpp[1]<<8);
【讨论】:
【参考方案2】:-859045864可以十六进制表示为0xCCCC0018。
读取第二个字节会得到 0x0018 = 24bpp。
这里最有可能发生的是 liczbaBitow 正在初始化为 0xCCCCCCCC;而您的plik.read
只写入低 16 位,而保持高 16 位不变。更改该行应该可以解决此问题:
int liczbaBitow = 0;
不过,尤其是这样的情况,最好使用与您的数据完全匹配的数据类型:
int16_t liczbaBitow = 0;
这可以在<cstdint>
找到。
【讨论】:
您可以添加调试模式下的 msvc 编译器使用0xCCCCCCCC
或更多值初始化整数类型,具体取决于类型。
@Machtl 谢谢,我添加了更多详细信息来解释答案。
非常感谢大家!真的很感激。
@user4581301 感谢您的建议,我已经添加了。以上是关于C++ - 从 BMP 文件中读取每个像素的位数的主要内容,如果未能解决你的问题,请参考以下文章