2011-08-02 14 views
2

このコードを使用して、bmpファイルからピクセルを取得しています。前の行ですでにヘッダーとパレットを読み込んでいるので、FILE *はピクセル配列の先頭に向いています。 最初の行を読み取ってOKを返します.1000が返されますが、2行目のピクセルを読み取ろうとすると0が返されます。BMPファイルからピクセルを読み込み、0を返します。

これはFILE *を受け取り、それらをbmp_typeに保存しようとします。 fila_alineadaは整列された行サイズで、パディングのためにこれを行う必要がありました。

bool leer_pixels_8bpp( FILE *fbmp, bmp_t *imagen, 
          const uint32_t fila_alineada, 
          const bool btopdown){ 
int32_t i; 
long x, y; 
int32_t height, width, contador; 
uint8_t *ptmp; 

uint8_t bufferfila[fila_alineada]; 

height = imagen->infoheader.height; 
width = imagen->infoheader.width; 
contador = height; 

i = btopdown ? 1 : -1; 
y = btopdown ? 0 : (height - 1); 

for (; contador--; y += i) /* row loop */ 
{ 
    /* reading row */ 
    if (fread(bufferfila, sizeof(uint8_t), fila_alineada, fbmp) != fila_alineada) 
    { /* HERE is the PROBLEM, it reads ok once, but in the second loop it returns 0 */ 
     fprintf(stderr, "Error reading pixels row.\n"); 
     return false; 
    } 

    ptmp = bufferfila; 
     /* saving pixels into bmp_t */ 
    for (x = 0L; x < width; x++) 
    { 
     imagen->pixels[y][x] = imagen->paleta.colores[ *ptmp++ ]; 
    } 

} 

return true; 

}

私は貴様のBMPのを試してみました!問題はここにあるのでしょうか、コード全体を見直すべきですか? 誰かが私に助けてくれることを願っています。ありがとうございます。

+0

本当に0を返しますか、または '' fila_alineada''と異なる値を返していますか?この場合、ファイルの終わりに達すると期待されます... – Fred

+0

(fread)ブロックの後にコードをコメントアウトできますか?ポインタが破損した場合、freadは失敗する可能性があります。 – Shash316

+0

おかげさまで、ありがとうございました。 ピクセルあたりのファイルビットの種類に応じて、leer_1bpp/8bpp/24bpp(3種類の機能)を呼び出すスイッチを使用していました。しかし、私はスイッチのそれぞれのケースで '休憩'が欠けていた。 ドットは分かっていますが、現在は動作しています。 私はfreadの値を見るためにデバッグをチェックしたかったのですが、何らかの理由でkdbgは現在のコンテキストでシンボルフリーダをしていませんが、そのブレークを入れる前にfread(.........)の戻り値を示しました。 とにかく読んでいるのですが、いくつかのftellを入れて何バイト読みとったのか分かりましたので、大丈夫です。 ありがとう! – nitrnitr

答えて

2

あなたのコードから、画像のwidthが読んでいないと思われます。むしろ、あなたは額をfila_alineadaで読んでいます。あなたは、fila_alineadaが "パディング"のために整列された行サイズであると言いましたが、BMPファイルは各行を4バイトの倍数に拡張するための十分なパディングしか持たないはずです... BITMAPINFOHEADERから実際のピクセル配列data-sizeをイメージの行数で除算することによって計算されます。画素配列データサイズは、ヘッダのオフセット0x22に格納される。私があなたが正しく推測したと思うように、高さはオフセット0x16にあります。したがって、引数fila_alineadaはかなり重複しています(削除することができます)。この値は誤って計算されている可能性があります。私は単純にヘッダーの情報を使って、画像の特定の行に情報を保存するのに必要なバッファのサイズを計算します。

第2に、ファイルからBITMAPINFOHEADER情報をいくつかの代表的なヘッダ構造であるバッファにコピーしようとしただけの場合は、コンパイラがバイト配列のために構造体を埋め込んでいる可能性があることに注意してください。安全上の理由から、単にファイルからヘッダー全体を読み取ってから、memcpy()を使用してバッファをBITMAPINFOHEADER構造体に書き込もうとするべきではありません。ファイルからヘッダー値を1つずつ読み込み、その値をBITMAPINFOHEADERを表す任意の構造体に個別に格納する必要があります。さもなければ、前者の場合、ファイルの最初のNバイトを読み込み、それを構造体にコピーするだけで、バイトアラインメントの問題や不正確な値のコピーが起こる可能性があります。その構造体から読み込みを試みる値は、ビットマップファイルに関連付けられた値を表しません。

+0

答えてくれてありがとう、私はすでに上記のように問題を解決しています、とにかく私はあなたに答えるでしょう! :) 1)私はfila_alineadaを使って、私が言ったように、行ごとにどれだけの量を読みなければならないかを計算しています。私は45pixelsの幅を持つ8bppのbmpを持っている場合、最初の行は360ビットを持つ必要があります。あなたが言ったように、行のサイズは4バイト(32ビット)でなければなりません。 360は32の倍数ではないので、私がしていることは次のようなものです:bitsperrow = width * bitsperpixel if(bitsperrow%32) bitsperrow + = 32 - (bitsperrow%32) – nitrnitr

+0

私は何ですか:bitsperrow = width * bitsperpixel; if(bitsperrow%32){ bitsperrow + = 32 - (bitsperrow%32)} 次に、bitperrowを8で割って、行(fila_alineada)のバイト量を取得します。 それはちょうど3行です! そして約2)、はい、私はそれを知っていた、infoheaderは整列した構造ではない、私は最初のbmpの魔法の数字を読んで、次に他のものを読む必要があった。 私は両方のヘッダを読み込んだらprintfで印刷しています。 もう一度ありがとう:) – nitrnitr

+0

あなたの計算はうまくいくようですが、ちょうどそれらのフープをジャンプする必要はありません...単純にBITMAPINFOHEADERフィールドオフセット0x22を使用してピクセルデータのバイト数を取得し、次にピクセル行数...これは、パディングオフセットを計算することなく、行あたりのバイト数を指定します。 – Jason