2017-09-30 124 views
0

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

Woman

这一次没有:

enter image description here

我不明白,我哪里错了,但比特深度表现出对所有三个图像的正确值。

这里是我的代码:通过读取BMP头为一系列字节,而不是整数的

#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; 
} 
+3

通常,经过一段时间或逗号后,用英文填写空格。此外,大写字母应该用于句子中的第一个单词。最后,对代码进行格式化,使其易读,并且我们不会浪费时间来破解它。 – nbro

+0

不便之处 – USERRR5

+2

代码建议。不要使用'double','pow'函数或任何浮点数来表示一些本来就是不可或缺的东西 – selbie

回答

2

让我们开始。为了使这个代码真正便携,我们将使用<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)); 

现在,我们已经有了在内存中的标头为字节数组,我们可以简单地施展每个头字段的内存地址回一个整数。参考bmp的wikipedia pagethe 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,以获得上述每个变量。

+0

位图标题只有54个字节,你可以使用'inputfile.read((char *)headerbytes,54);' –

+0

比你多得多..我想使用库函数的次数少,以便我可以理解属性的bmp文件。 – USERRR5

+1

'operator >>'不应该用于读取二进制数据。如你所知,它会跳过当前编码中被认为是空白的字节。你可以使用'noskipws',但最好使用'read',这对于二进制数据是明确的。 –

0

该错误正在读入signed char。这应该修复它:

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(); 
} 

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

+0

我想尽可能少地使用库函数,你会好心告诉我应该如何改变我的代码。我没有得到关于unsigned char的信息。你能帮我解决吗? – USERRR5

+0

@ USERRR5我向你展示了如何更改你的代码。用上面的代码替换数据中现有的for循环读取。 'char'是默认签名的,所以它的值不是0-255,而是-128到127.使用'int'可以正确保存0-255。 –