struct und fread -> falscher wert in struct??



  • Hallo

    Ich versuche gerade einen Bitmap-Header in ein Struct einzulesen, aber alle Werte bis auf den ersten werden falsch abgeglegt in der Structur!
    Nach langen Stunden hab ich was über "Struct Padding" gefunden..
    So wie es ausschaut werden nach den short int noch 2 byte eingefügt, aber warum werden die bytes nicht am structurende eingefügt sonder mittendrinn??

    1. Wie kann ich den Header richtig auslesen? -> Liegt der Fehler am fread?
    2. Wenn ich das Bild auslesen will mit einer Pixel-Structur von 3Byte, wird dann das Bild ebenfalls falsch gelesen?

    Verwende Code:Blocks mit MinGW+GCC

    Hier mein Code zum Testen

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    // #include <windows.h>
    
    void wait ()
    {
        printf("\n Weiter mit Enter");
        setvbuf(stdin,NULL,_IONBF,0);
        setvbuf(stdin,NULL,_IOFBF,BUFSIZ);
        getchar();
    }
    
    struct bmp_header
    {
    
        unsigned short bfType;       //   2 Byte    ASCII-Zeichenkette "BM" -> Dezimal 19778
        unsigned int bfSize;         //   4 Byte    Größe der BMP-Datei in Byte. (unzuverlässig)
        unsigned int bfReserved;     //   4 Byte    Reserve ist immer 0
        unsigned int bfOffBits;      //   4 Byte    Offset der Bilddaten in Byte vom Beginn der Datei an.
    
    };
    
    int main()
    {
        char pfad[] = "c:\\temp\\test.bmp";
        FILE *fp;                   // File Pointer
        struct bmp_header bmp_info; // Variable mit BMP_Header Struktur
    
        /* ********************  ANFANG - Datei einlesen ****************** */
    
        if ((fp=fopen(pfad, "rb")) == NULL)             /*Datei zum Lesen öffnen */
        {
            printf("\n Konnte Bitmap nicht öffnen ");
            return 1;                                   /* keine Datei vorhanden  */
        }
        else
        {
    
            fread(&bmp_info,sizeof(bmp_info),1,fp);   /* Einlesen eines Blocks  */
            fclose(fp);
            printf("bfType = %hu \n",bmp_info.bfType);
            printf("bfSize = %u \n",bmp_info.bfSize);
            printf("bfReserved = %i \n",bmp_info.bfReserved);
            printf("bfOffBits = %i \n\n",bmp_info.bfOffBits);
    
            printf("sizeof bfType = %i \n",sizeof(bmp_info.bfType));
            printf("sizeof bfSize = %i \n",sizeof(bmp_info.bfSize));
            printf("sizeof bfReserved = %i \n",sizeof(bmp_info.bfReserved));
            printf("sizeof bfOffBits = %i \n",sizeof(bmp_info.bfOffBits));
        }
    
        /* ********************  ENDE - Datei einlesen ****************** */
    
        wait();
        return 0;
    }
    

    Ergebniss: (bfReserved sollte 0 sein.. ist es aber nicht)
    http://img412.imageshack.us/img412/7025/struct.png

    PS: bin noch nicht so gut in c



  • ich denke aus performance gründen wird dein header nach dem optimieren

    struct bmp_header
    {
    
        unsigned int bfType;       //   2 Byte    ASCII-Zeichenkette "BM" -> Dezimal 19778
        unsigned int bfSize;         //   4 Byte    Größe der BMP-Datei in Byte. (unzuverlässig)
        unsigned int bfReserved;     //   4 Byte    Reserve ist immer 0
        unsigned int bfOffBits;      //   4 Byte    Offset der Bilddaten in Byte vom Beginn der Datei an.
    
    };
    

    aussehen.
    eigentlich muß man aber das structure packing explizit einschalten,also solte es normalerweise nicht passieren



  • Das eigentliche Problem nennt sich "Alignment" (nicht Padding).

    Schau mal auf http://en.wikipedia.org/wiki/BMP_file_format
    Dort steht, daß du die ersten beiden Zeichen ("BM") getrennt einlesen mußt, s. "Equivalent C-Language Header".



  • Hallo,
    das Problem wurde schon genannt: Alignment/Padding. Wenn du dir die Größe deiner Struktur mit sizeof(struct bmp_header) anguckst, dann siehst du, warum die Daten nicht da landen, wo sie sollen. Mit einem

    #pragma pack(1) // Alignment abschalten.
    struct bmp_header {
    ...
    };
    // Hier eventuell noch weitere Strukturen deklarieren.
    ...
    #pragma pack() // Alignment auf Anfangszustand setzen
    

    Sollte das Problem behoben sein. Oder nimm gleich die in der windows.h verwendeten Strukturen, da ist das pragma pack ding schon um die Strukturen drum rum gebaut.

    Gruß,
    B.B.


Anmelden zum Antworten