C++ - 从 BMP 文件中读取每像素的位数
C++ - Reading number of bits per pixel from BMP file
我正在尝试获取 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。我不知道它来自哪里...我迷路了。
有什么想法吗?
-859045864可以用十六进制表示为0xCCCC0018。
读取第二个字节得到 0x0018 = 24bpp。
这里最有可能发生的是,liczbaBitow 正在被初始化为 0xCCCCCCCC;而您的 plik.read
仅写入低 16 位而高 16 位保持不变。更改该行应该可以解决此问题:
int liczbaBitow = 0;
不过,尤其是像这样的东西,最好使用与您的数据完全匹配的数据类型:
int16_t liczbaBitow = 0;
这可以在 <cstdint>
中找到。
为了澄清@TheBluefish 的回答,这段代码有错误
// Read number of bytes used per pixel
int liczbaBitow;
plik.read((char*)&liczbaBitow, 2);
当您使用 (char*)&libczbaBitow
时,您正在获取一个 4 字节整数的地址,并告诉代码将 2 个字节放在那里。
该整数的其他两个字节未指定且未初始化。在这种情况下,它们是 0xCC
因为这是系统使用的堆栈初始化值。
但是,如果您从另一个函数调用它或重复调用它,则堆栈可能包含其他虚假值。
如果您初始化变量,您将获得您期望的值。
但是还有另一个错误.. 字节顺序在这里也很重要。此代码假设机器本机字节顺序与文件规范中的字节顺序完全匹配。有许多不同的位图格式,但根据您的参考,维基百科文章说:
All of the integer values are stored in little-endian format (i.e. least-significant byte first).
这和你的一样,显然也是x86小端。其他字段未定义为小端,因此在您继续解码图像时,您必须注意它。
理想情况下,您读入字节数组并将字节放在它们所属的位置。
参见 Convert Little Endian to Big Endian
int libczbaBitow;
unsigned char bpp[2];
plik.read(bpp, 2);
libczbaBitow = bpp[0] | (bpp[1]<<8);
我正在尝试获取 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。我不知道它来自哪里...我迷路了。
有什么想法吗?
-859045864可以用十六进制表示为0xCCCC0018。
读取第二个字节得到 0x0018 = 24bpp。
这里最有可能发生的是,liczbaBitow 正在被初始化为 0xCCCCCCCC;而您的 plik.read
仅写入低 16 位而高 16 位保持不变。更改该行应该可以解决此问题:
int liczbaBitow = 0;
不过,尤其是像这样的东西,最好使用与您的数据完全匹配的数据类型:
int16_t liczbaBitow = 0;
这可以在 <cstdint>
中找到。
为了澄清@TheBluefish 的回答,这段代码有错误
// Read number of bytes used per pixel
int liczbaBitow;
plik.read((char*)&liczbaBitow, 2);
当您使用 (char*)&libczbaBitow
时,您正在获取一个 4 字节整数的地址,并告诉代码将 2 个字节放在那里。
该整数的其他两个字节未指定且未初始化。在这种情况下,它们是 0xCC
因为这是系统使用的堆栈初始化值。
但是,如果您从另一个函数调用它或重复调用它,则堆栈可能包含其他虚假值。
如果您初始化变量,您将获得您期望的值。
但是还有另一个错误.. 字节顺序在这里也很重要。此代码假设机器本机字节顺序与文件规范中的字节顺序完全匹配。有许多不同的位图格式,但根据您的参考,维基百科文章说:
All of the integer values are stored in little-endian format (i.e. least-significant byte first).
这和你的一样,显然也是x86小端。其他字段未定义为小端,因此在您继续解码图像时,您必须注意它。
理想情况下,您读入字节数组并将字节放在它们所属的位置。 参见 Convert Little Endian to Big Endian
int libczbaBitow;
unsigned char bpp[2];
plik.read(bpp, 2);
libczbaBitow = bpp[0] | (bpp[1]<<8);