代码之家  ›  专栏  ›  技术社区  ›  MindRoller

C++-从BMP文件读取每个像素的位数

  •  0
  • MindRoller  · 技术社区  · 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。我不知道它来自哪里……我很迷茫。

    有什么想法吗?

    2 回复  |  直到 8 年前
        1
  •  3
  •   Community datashaman    7 年前

    为了澄清@TheBluefish的答案,此代码有错误

    // Read number of bytes used per pixel
    int liczbaBitow;
    plik.read((char*)&liczbaBitow, 2);
    

    当您使用 (char*)&libczbaBitow ,取一个4字节整数的地址,并告诉代码在那里放2个字节。

    该整数的其他两个字节未指定且未初始化。在这种情况下,他们 0xCC 因为这是系统使用的堆栈初始化值。

    但如果您从另一个函数调用此函数或重复调用此函数,则可以预期堆栈会包含其他伪值。

    如果您初始化变量,您将获得所需的值。

    但还有另一个错误…字节顺序在这里也很重要。这段代码假设机器本机字节顺序与文件规范中的字节顺序完全匹配。有许多不同的位图格式,但根据您的参考,维基百科文章说:

    所有整数值都以小端格式存储(即先存储最低有效字节)。

    这与您的相同,它显然也是x86 little-endian。其他字段没有定义为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
  •  2
  •   user820304 user820304    8 年前

    -859045864可以用十六进制表示为0xCCCC0018。

    读取第二个字节得到0x0018=24bpp。

    这里最可能发生的情况是,liczbaBitow正在初始化为0xCCCCCCC;而您的 plik.read 只写入低16位,而保持高16位不变。更改该行应该可以解决此问题:

    int liczbaBitow = 0;

    尽管如此,尤其是对于这样的情况,最好使用与您的数据完全匹配的数据类型:

    int16_t liczbaBitow = 0;

    这可以在中找到 <cstdint> .