读取bmp文件头大小

时间:2017-09-30 16:15:26

标签: c++

我正在尝试查找文件大小,文件头大小宽度和bmp文件的高度。我研究了bmp文件的格式和文件中的字节排列。 当我尝试此代码时,它显示不同文件的错误宽度和高度。 到目前为止,我已经尝试了三张图片。这一个图像可以产生正确的测量结果。

Woman

这个没有:

enter image description here

我不明白我哪里出错了,但是比特深度显示了所有三张图片的正确值。

这是我的代码:

#include<iostream>
#include<fstream>
#include<math.h>

using namespace std;


int main() {
    ifstream inputfile("bmp.bmp",ios::binary);
    char c; int imageheader[1024]; 

    double filesize=0; int width=0; int height=0;int bitCount = 0;

    for(int i=0; i<1024; i++) {
        inputfile.get(c); imageheader[i]=int(c);
    }

    filesize=filesize+(imageheader[2])*pow(2,0)+(imageheader[3])*pow(2,8)+(imageheader[4])*pow(2,16)+(imageheader[5])*pow(2,24);

    cout<<endl<<endl<<"File Size:  "<<(filesize/1024)<<" Kilo Bytes"<<endl;

    width=width+(imageheader[18])*pow(2,0)+(imageheader[19])*pow(2,8)+(imageheader[20])*pow(2,16)+(imageheader[21])*pow(2,24);

    cout<<endl<<"Width: "<<endl<<(width)<<endl;

    height=height+(imageheader[22])*pow(2,0)+(imageheader[23])*pow(2,8)+(imageheader[24])*pow(2,16)+(imageheader[25])*pow(2,24);
    cout<<endl<<"Height: "<<endl<<(height)<<endl;

    bitCount=bitCount+(imageheader[28])*pow(2,0)+(imageheader[29])*pow(2,8);
    cout<<endl<<"Bit Depth: "<<endl<<(bitCount)<<endl;
}

2 个答案:

答案 0 :(得分:2)

让我们从一系列字节读取BMP头开始,而不是整数。为了使此代码真正可移植,我们将使用<stdint>类型。

#include <fstream>
#include <stdint.h>

int main()
{

    ifstream inputfile("D:/test.bmp", ios::binary);
    uint8_t headerbytes[54] = {};

    inputfile.read((char*)headerbytes, sizeof(headerbytes));

现在我们已经将内存中的标头作为字节数组,我们可以简单地将每个标头字段的内存地址转换回整数。引用wikipedia page代表bmp和the layout diagram

    uint32_t filesize = *(uint32_t*)(headerbytes+2);
    uint32_t dibheadersize = *(uint32_t*)(headerbytes + 14);
    uint32_t width = *(uint32_t*)(headerbytes + 18);
    uint32_t height = *(uint32_t*)(headerbytes + 22);
    uint16_t planes = *(uint16_t*)(headerbytes + 26);
    uint16_t bitcount = *(uint16_t*)(headerbytes + 28);

现在,该代码的精明读者将认识到BMP头的各个部分以小端格式存储。并且上面的代码依赖于您拥有x86处理器或字节布局为Little Endian的任何其他架构。在大端机器上,您必须为上面的每个变量应用一个变换方法,从LE转换为BE。

答案 1 :(得分:0)

该错误正在读取已签名的字符。这应该解决它:

for(int i = 0; i < 1024; i++)
{
    //inputfile.get(c); imageheader[i] = int(c);

    // This version of get returns int, where -1 means EOF.  Should be checking for errors...
    imageheader[i] = inputfile.get();
}

其他人评论了对代码的改进,所以我不会打扰。