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*)&amp;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;

这可以在&lt;cstdint&gt;找到。

【讨论】:

您可以添加调试模式下的 msvc 编译器使用 0xCCCCCCCC 或更多值初始化整数类型,具体取决于类型。 @Machtl 谢谢,我添加了更多详细信息来解释答案。 非常感谢大家!真的很感激。 @user4581301 感谢您的建议,我已经添加了。

以上是关于C++ - 从 BMP 文件中读取每个像素的位数的主要内容,如果未能解决你的问题,请参考以下文章

Fread 返回 0,从 BMP 文件中读取像素

C++ 位图每像素位

读取 BMP 文件 C++(读取 BMP 标头时出现问题)

从 bmp 文件中读取 RGB 像素

如何使用 C++ 正确计算 BMP 图像中每个像素的字节数?

用C语言读取16位bmp图片的每个像素的信息~