9
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main()
{
    FILE* bmp = NULL;
    uint32_t offset;
    uint8_t* temp = NULL;
    size_t read;
    unsigned int x_dim = 600, y_dim = 388;

    bmp = fopen("test_colour.bmp", "r");

    if (!bmp)
        return -1;

    /* Get the image data offset */
    fseek(bmp, 10, SEEK_SET);
    fgets((char*)&offset, 4, bmp);

    printf("Offset = %u\n", offset);

    temp = malloc(3*x_dim*y_dim*sizeof(uint8_t));

    if (!temp)
        return -1;

    /* Go the the position where the image data is stored */
    fseek(bmp, offset, SEEK_SET);

    /* Copy image data to array */
    printf("%u bytes requested!\n", 3*x_dim*y_dim);
    read = fread((void*)temp, sizeof(uint8_t), 3*x_dim*y_dim, bmp);
    printf("%Iu bytes read!\n", read);

    fclose(bmp);
    free(temp);

    return 0;
}

上記のコードを使用して、24ビット/ピクセルのBMP画像のRGBデータを配列に読み取ります。画像データが開始するファイルの先頭からのオフセット(BMPヘッダーの後)は、BMP仕様に従ってオフセット10で指定されます。上記のコードを実行すると、次の出力が得られます。

Offset = 54
698400 bytes requested!
33018 bytes read!

ファイルサイズが698454バイト(= 698400 + 54)であるため、オフセット出力は正しいようです。ただし、によって返される値はfread()、画像データ全体を読み取ることができなかったことを示しているようです。ただし、その後、temp配列内のデータを使用してRGBデータをグレースケールに変換し、このデータをBMPファイルに再度書き込みます。出力画像を視覚的に確認してもエラーは表示されません。つまり、fread()表示が異なるように見えますが、最初に入力画像全体を実際に読み取ったように見えます。

誰かがこの行動を説明できますか?

4

1 に答える 1

31

(私はあなたが Windows を使っているに違いない)

bmp = fopen("test_colour.bmp", "r");

する必要があります

bmp = fopen("test_colour.bmp", "rb");

ファイルが Windows でテキスト モードで開かれている場合、Windows がテキスト ファイルの EOF マーカーと見なす 0x1a (Ctrl-Z) バイトにヒットすると、ランタイムは読み取りを停止します。Ctrl-Z を押さなくても、Windows が CR/LF シーケンスを 1 つの LF 文字に変換すると、データが破損します。

ただし、部分的なファイルの読み取りから適切な画像を取得できる理由は説明できません (運が良かっただけですか?)。

fread()実装は、要求されたバイト数 (またはほぼ同じ - 数はブロック サイズの倍数に切り捨てられる) をバッファーに読み取り、バッファーをスキャンして、バッファーから画像をレンダリングすることができます。変換する CR/LF シーケンスと Ctrl-Z EOF フラグ。

したがって、 がfread()返されても33018、実際にはバッファはファイルからのデータでほぼ完全に書き込まれています。データは 100% 正しいわけではありません (たとえば、一部の CR 文字が破棄された可能性があります)、または完全ではありませんが、この場合は、期待どおりの画像をレンダリングするのに十分近いものです。

もちろん、これは単にこの特定のランタイムが現在どのように動作するかを観察したものです。将来、(または現在のすべてのシステムでさえ) 常にそのように動作するとは限りません。

于 2012-07-30T07:53:13.097 に答える