3

24 ビットの BMP ファイルから RGB 値を取得しようとしていました。私が使用している画像は小さな画像で、すべて赤なので、すべてのピクセルの BGR 構成はB:0 G:0 R:255. 私はこれをします:

int main(int argc, char **argv)
{
    principal();
    return 0;
}

typedef struct {
    unsigned char blue;
    unsigned char green;
    unsigned char red;
} rgb;

typedef struct {
    int ancho, alto;
    rgb *pixeles[MAX_COORD][MAX_COORD];
} tBitmapData;

void principal()
{

    FILE *fichero;
    tBitmapData *bmpdata = (tBitmapData *) malloc(sizeof(tBitmapData));
    rgb *pixel;
    int i, j, num_bytes;
    unsigned char *buffer_imag;
    char nombre[] = "imagen.bmp";
    fichero = fopen(nombre, "r");
    if (fichero == NULL)
            puts("No encontrado\n");
    else {
            fseek(fichero, 18, SEEK_SET);
            fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);
            printf("Ancho: %d\n", bmpdata->ancho);
            fseek(fichero, 22, SEEK_SET);
            fread(&(bmpdata->alto), sizeof((bmpdata->alto)), 4, fichero);
            printf("Alto: %d\n", bmpdata->alto);
    }

    num_bytes = (bmpdata->alto * bmpdata->ancho * 3);
    fseek(fichero, 54, SEEK_SET);
    for (j = 0; j < bmpdata->alto; j++) {
            printf("R   G   B Fila %d\n", j + 1);
            for (i = 0; i < bmpdata->ancho; i++) {
                    pixel =
                        (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                       bmpdata->ancho * 3);
                    fread(pixel, 1, sizeof(rgb), fichero);
                    printf("Pixel %d: B: %3d G: %d R: %d \n", i + 1,
                           pixel->blue, pixel->green, pixel->red);
            }
    }
    fclose(fichero);
}

問題は、それらを印刷すると、最初のピクセルは問題ありB:0 G:0 R:255ませんが、その後 に変化し始め、次に に変化するB:0 G:255 R:0ことB:255 G:0 R:0です。幅が 10 ピクセルの場合、変更は 10 ピクセルごとに発生します。

4

2 に答える 2

5

BMP ファイル形式では、4 バイトの倍数に切り上げるために、ピクセル データの各行がパディングされる場合があります。

10 個の 24 ビット ピクセルがある場合、それは 30 バイトであり、その後に 2 バイトのパディングが続きます。コードはパディングをスキップしません。

于 2011-03-19T00:39:25.693 に答える
2

私はあなたのfread(3)電話が間違っていると思います:

        fread(&(bmpdata->ancho), sizeof((bmpdata->ancho)), 4, fichero);

4*sizeof((bmpdata->ancho))これは、バイトをに読み込むように要求しますintsizeof((bmpdata->ancho))私はリターンを想定し4ているので、これらの2つの呼び出しで無関係なメモリをスクライブしていると思います。をに変更し4ます1-あなたは1つのアイテムだけを読んでいます。

使用することはありませんnum_bytes; 消して。未使用のコードは、使用済みのコードについて考えるのをはるかに難しくします。:)

必要なメモリの3倍のメモリを割り当てています。

                pixel =
                    (rgb *) malloc(sizeof(rgb) * bmpdata->alto *
                                   bmpdata->ancho * 3);

構造内の3赤、緑、青のそれぞれを説明しようとしているように見えますが、構造の正しいサイズはすでにわかっています。(32ビットCPUの便利なアラインメントのためのバイト、またはアラインメントのためのバイト(それぞれ独自のバイト境界上)、またはアラインメントされたデータの操作を本当に楽しんでいる64ビットシステムのバイトでさえありますバイト境界。)rgbsizeof(rgb)412char4248

そして私が注意する最後のこと:

                fread(pixel, 1, sizeof(rgb), fichero);

Cコンパイラは構造体に穴を挿入できるため、ディスク上のフォーマットがメモリ内の構造体の定義と一致するとは限りません。GNU C拡張__packed__属性を使用するか、 bmp形式用に設計されたライブラリまたは構造を使用してからデータを読み取る必要があります。これがあなたにとって楽しいプロジェクトである場合は、間違いなく__packed__ルートを試してください。うまくいく場合、うまくいく場合、うまくいかない場合は、うまくいけば、その理由を学び、コードを書き直して、構造の各要素を手動でロードします。ビットマップを正しく解析できるものを取得しようとしているだけの場合は、すでに画像を正しく解析している事前に作成されたライブラリを見つけてみてください。

(もちろん、画像の解析を正しく行うことは非常に重要です。CVEには、攻撃者がプログラムを制御できるようにする不正な形式の画像エクスプロイトのリストがあり、それらの多くはリモートで悪用可能です。)

于 2011-03-19T00:53:42.070 に答える