2017-09-30 42 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。 –