2016-03-19 8 views
0

私は画像を扱っています。私はヘッダーからそれの幅と高さを抽出したいと思います。ファイルのヘッダを解析する

幅は、それらが特定のインデックスで表現される位置

size 
    4B width 
    4B height 

で表されています。

Iは、それらの各々はそうforループ

for (int i = index ; i <4 ;i++){ 
    cout << hex<< memory[i]; 
} 

またはIであっても、それが

を使用して数に変換する試みを使用して、4Bを有し、それを解析し、コード

ifstream f(name, ios::binary | ios:: in); // reading a file in binary 
    ostringstream ob; 

    if (f.fail()){ // fail test 
     return false; 
    } 

    f.seekg (0, f.end); 
    int length = f.tellg(); // length of the file 
    memory = new char[length]; // allocate array of chars 
    f.read (memory, length); // read the content of the file into an array 
    f.seekg (0, f.beg); // point back at the beginning of the file. 

でそれを抽出しようとしました

string a; 
    for (int i = index; i < 4 ;i++{ 
     a+=memory[i]; 
    } 
    cout << atoi(a.c_str()) << endl; 

数値を出力する必要がありますが、読めない形式を出力します。

+0

「インデックス」とは何ですか? for(int i = index; i MikeCAT

+2

'new type [count]'を使わず、代わりに 'vector 'を使ってください。とにかく、サイトルールに準拠するための質問のための最小限の例を抽出する必要があります。 ATMは話題にはなりません。 –

+0

ヘッダのフォーマットへのリンクがありますか?それは高さと幅である最初の2つの値ですか?ドキュメントでは、数字を格納するために "エンディアン"が使用されていることを教えていますか? – Galik

答えて

0

std::coutデータがcharの場合、文字として渡されるデータを印刷するので、印刷する前にキャストしてください。ファイル内の番号はリトルエンディアンである場合、次のように整数に変換することができます

for (int i = 0 ; i < 4 ; i++) { 
    cout << hex<< (int)(unsigned char)memory[index + i]; 
} 

// Use #include <cstdint> for using type uint32_t and uint8_t 
uint32_t num = 0; // the converted number will be here 
for (int i = 0 ; i < 4 ; i++) { 
    num |= (uint8_t)memory[index + i] << (uint32_t)(8 * i); 
} 
4

あなたは、むしろ、それを読ん後のファイルの先頭に探しています前より。あなたはread()seekg()ラウンド切り替える必要があります:

f.seekg (0, f.beg); // point back at the beginning of the file. 
f.read (memory, length); // read the content of the file into an array 
1

タイトルに記載された問題の迅速な答えを、あなたが指定した入力ファイルを見ることで、あなたは単純に3本のラインを読むことができる、最初のスキップ次の2行からそれぞれ1つの整数を抽出します。

ですから、ファイル内でこのような複数のエントリを持っている場合は、ループ内で上記の操作を行い

int width, height; 

std::string input; 
std::istringstream is; 

std::getline(stream, input); // One line for the "size" string 

std::getline(stream, input); // One line for the width 
is.str(input) 
is >> width; 

std::getline(stream, input); // One line for the height 
is.str(input) 
is >> height; 

のようなもの。

ファイルが実際に、それはさらに簡単ですが、数字だけ、あなたが表示されたテキストが含まれていない場合:

int width, height; 
stream >> width >> height; 

それとも、複数のエントリ

while (stream >> width >> height) { ... } 
2

がある場合はしないでください非常に多くの情報を提供していますので、ここで少し推測してみてください。しかし、これは私がファイルの読み方に近づく方法です:

主な機能は、手動メモリ割り当てを使用しないでください。 std::vector(そのためのもの)。また、の文字配列のデータを正しい型からのキャスト変数にコピーします。これにより、配置が正しいことが保証されます(の文字配列にキャストされません)。もう1つのアプローチは、ファイルから直接入力された変数をchar*にキャストすることです。

int main(int, char* argv[]) 
{ 
    // first parameter needs to be file name 
    std::string name = argv[1] ? argv[1]:""; 

    std::ifstream ifs(name, std::ios::binary|std::ios::ate); // open at end 

    if(!ifs) 
    { 
     std::cerr << std::strerror(errno) << '\n'; 
     return EXIT_FAILURE; 
    } 

    if(ifs.tellg() < 8) // too small 
    { 
     std::cerr << "Bad image file, too short" << '\n'; 
     return EXIT_FAILURE; 
    } 

    // Don't allocate memory manually, use a container 
    std::vector<char> image(ifs.tellg()); // big enough for whole file 

    ifs.seekg(0); // back to beginning 

    if(!ifs.read(image.data(), image.size())) 
    { 
     std::cerr << std::strerror(errno) << '\n'; 
     return EXIT_FAILURE; 
    } 

    // copy raw data into variables 

    std::uint32_t width; // 4 bytes wide integer 
    std::uint32_t height; // 4 bytes wide integer 

    std::copy(&image[4], &image[ 8], (char*)&width); // offset 4 bytes 
    std::copy(&image[8], &image[12], (char*)&height); // offset 8 bytes 

    // at this point a lot depends on the system architecture and 
    // how the number is stored in the file. The documentation 
    // should tell you if it is little-endian or big-endian 

    // you may have to do manual jiggery-pokery 
    // to change endienness 

    std::cout << "width : " << width << '\n'; 
    std::cout << "height: " << height << '\n'; 
}