Hexadezimal aus Binär-Datei lesen



  • Da die Funktion 'Read' nicht weiß, was sie einlesen soll, erwartet sie einfach einen 'char *'. Da du als Anwender der Funktion aber weißt, das an der entsprechenden Stelle ein int (4 Byte) stehen, mußt du einfach den Zeiger entsprechend casten:

    int breite=0;
    BildFile.read(static_cast<char *>(&breite), sizeof(int));
    

    So einfach ist das...



  • Na, in dem Fall ist wohl tatsächlich ein Cast angebracht (und notwendig):

    BildFile.read(reinterpret_cast<char*>(&breite),4);
    

    Alternativ kannst du den int-Wert auch aus den vier Bytes zusammenrechnen:

    unsigned char data[4];
    BildFile.read(data,4);
    breite = data[0]*0x01000000 + data[1]*0x00010000 + data[2]*0x00000100 + data[3];
    

    (eventuell sind die indizes auch andersherum - das hängt mit big-endian/little-endian zusammen)



  • In windows.h (genauer in wingdi.h) stehen die Bitmapheader-Strukturen bereit.
    Du musst Dir bloss Instanzen davon anlegen und den Bitmapheader deiner Bitmap da einlesen.
    So bekommst Du bequemen Zugang zu allen Infos.



  • @CStoll:
    funktioniert beides nicht. komisch komisch

    @gerie: sorry, was meinst du?
    ich hab da die :
    typedef struct tagBITMAP
    {...}
    gefunden, womit leider noch immer das Problem des einlesens bleibt.



  • DerHorst schrieb:

    @CStoll:
    funktioniert beides nicht. komisch komisch

    Wie drückt sich dieses "funktioniert nicht" in Worten aus?



  • es werden konstanten geliefert, egal wo ich mit seekg "hingehe".
    Wenn ich die Indizes in umgekehrter Reihenfolge verwende, wird immer 16 als ergebnis geliefert (bei der Additionsvariante)
    Bei der Cast-variante werden auch nur Zahlen geliefert, die einer Bereichsüberschreitung nahe kommen.
    Ich habe es auch schon so versucht:

    unsigned char data[50];
    reite = data[i]*0x01000000 + data[j]*0x00010000 + data[k]*0x00000100 + data[l];
    //mit: int i,j,k,l
    //gleiches Resultat

    komisch wa?



  • So wie 'gerie' geschrieben hat, ist es der einfachste Weg direkt die Bitmap-Struktur(en) zu nutzen:

    struct tagBITMAPFILEHEADER bmFile;
    struct tagBITMAPINFOHEADER bmInfo;
    
    BildFile.read(reinterpret_cast<char*>(&bmFile), sizeof(struct tagBITMAPFILEHEADER));
    BildFile.read(reinterpret_cast<char*>(&bmInfo), sizeof(struct tagBITMAPINFOHEADER));
    

    Nun sollten in den entsprechenden Membern von 'bmInfo' die richtigen Werte stehen, z.b. bmInfo.biWidth oder bmInfo.biHeight.

    Am besten du schaust mal in die MSDN-Hilfe unter 'Bitmap Storage'.

    P.S. Ich komme rechnerisch nur auf 18 Bytes (statt 36) zum Auslesen der Breite (und Höhe)...



  • DerHorst schrieb:

    es werden konstanten geliefert, egal wo ich mit seekg "hingehe".

    Häh?

    Wenn ich die Indizes in umgekehrter Reihenfolge verwende, wird immer 16 als ergebnis geliefert (bei der Additionsvariante)
    Bei der Cast-variante werden auch nur Zahlen geliefert, die einer Bereichsüberschreitung nahe kommen.

    Bist du sicher, daß du an der richtigen Stelle gelandet bist?
    Vielleicht solltest du dir mal ansehen, wie der BMP Header aufgebaut ist (bei Offset 36 bist du mitten in der Größenangabe für die Bilddaten).



  • Th hats gezeigt
    Hier nochmal:

    #include<fstream> 
    
    using namespace std;
    #include <windows.h>
    
    int main() 
    { 
    
        BITMAPFILEHEADER eins;
        BITMAPINFOHEADER zwei;
        ifstream ein;
        ein.open("c:\\tests.bmp", ios_base::binary);
        ein.read((char*)&eins, sizeof BITMAPFILEHEADER);
        ein.read((char*)&zwei, sizeof BITMAPINFOHEADER);      
       //...
    }
    


  • Vielleicht hilft dir ja ein lauffähiges Beispiel weiter:

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    typedef long int32;
    
    void bmpWidthAndHeight(const char *path)
    {
        int32 width, height;
    
        ifstream bmp(path);
        bmp.seekg(0x12);
        bmp.read(reinterpret_cast<char*>(&width), 4);
        bmp.read(reinterpret_cast<char*>(&height), 4);
        bmp.close();
    
        cout << "width:\t" << width << "\nheight\t" << height << endl;
    }
    
    int main()
    {
        bmpWidthAndHeight("test.bmp");
    }
    

    Um die Header komplett auszulesen, solltest Du aber, wie schon erwähnt wurde, Bitmap Strukturen aus dem MSDN, wie zum Beispiel BITMAPINFOHEADER verwenden.



  • Konstruktör schrieb:

    Vielleicht hilft dir ja ein lauffähiges Beispiel weiter:[cpp]#include <fstream>

    Jedenfalls ist es nicht sinnvoll eine Bitmap im Textmodus zu öffnen.



  • @ TH & CStoll:

    P.S. Ich komme rechnerisch nur auf 18 Bytes (statt 36) zum Auslesen der Breite (und Höhe)...

    Jo, da habt ihr Recht, das war eines dieser vielen Vertsändnisprobleme, die ich beim Handling mit BMP-Dateien hatte/habe - gruß an die Zahlensysteme 😉

    und:
    Juchhuu, hab es hinbekommen !!!
    Dank euch allen!!
    Wie meine Abendlektüre aussieht, is ja klar:

    Bitmap Strukturen aus dem MSDN

    Ich mach es jetzt mi Variante 2 - Variante 1 hat nicht hingehauen.

    struct tagBITMAPFILEHEADER bmFile;
    struct tagBITMAPINFOHEADER bmInfo;
    ...
    if ( OpenPic->Execute() )
    	{
    	AnsiString FileName=OpenPic->FileName;
        ifstream BildFile;
        BildFile.open(FileName.c_str(), ios::binary);
    //Variante 1
    /*
    	BildFile.read(reinterpret_cast<char*>(&bmFile), sizeof(struct tagBITMAPFILEHEADER));
    	BildFile.read(reinterpret_cast<char*>(&bmInfo), sizeof(struct tagBITMAPINFOHEADER));
    */
    //Variante 2
        BildFile.seekg(0x12);
        BildFile.read(reinterpret_cast<char*>(&width), 4);
        BildFile.read(reinterpret_cast<char*>(&height), 4);
    
        BildFile.close(); //unnuetz, hab ich mir aber so angewoehnt
        }
    
    Form1->Edit1->Text=IntToStr(width);
    Form1->Edit2->Text=IntToStr(height);
    Form1->Edit3->Text=IntToStr(bmInfo.biWidth);
    Form1->Edit4->Text=IntToStr(bmInfo.biHeight);
    

    jetzt gibts Bier - auf euch!!

    DerHorst 😃



  • Du solltest das bitmap file parsen und nicht einfach an einem fixen offset was rauslesen. Also erst header 'BM' checken, dann size vom BITMAPFILEHEADER (bfSize) checken, dann BITMAPFILEHEADER lesen, dann size vom BITMAPINFOHEADER (biSize) checken, dann BITMAPINFOHEADER lesen. Dann biCompression, biPlanes, biBitCount etc. checken was für ein Format das ist und ob du damit was anfangen kannset etc., und dann über bfOffBits die Bilddaten suchen und lesen.

    Am einfachsten und schnellsten (sowohl beim Programmieren als auch in der Ausführung) ist es aber immernoch wenn du die ganze Daten mit einem einzigen riesen read in den Speicher holst und dann alles checkst/interpretierst.


Anmelden zum Antworten