C++ Monochrom-Bitmap erstellen



  • Hallo zusammen,

    seit heute bastle ich ein wenig an einem Programm in C++, welches mir eine 2 farbige Bitmap erstellen
    soll. Dabei soll quasi die Bitmap als ASCII Code in eine leere Datei geschrieben werden.
    Wie eine Bitmap aus Hexcode aufgebaut ist, weiß ich schon, bzw. habe ich verstanden...
    Nun wollte ich das ganze mal in C++ umsetzen und stoße dabei jedoch schon auf den ein oder anderen Fehler.
    Hier mal meine Struktur für den BitmapFileHeader:

    typedef struct bmpFileHeader
    {
    	UINT16 bmType;
    	UINT32 fileLength;
    	UINT16 reserved1;
    	UINT16 reserved2;
    	UINT32 bmOffset;
    };
    

    Hier dann die Initialisierung in einer Funktion:

    bmphex2file(string filename, unsigned int width, unsigned int height, DWORD pxdata)
    {
        ofstream bmpfile;
        bmpfile.open(filename,  ios::binary | ios::out);
        //[...]anderer Kram
        bmpFileHeader BFHEADER = { ('B' | 'M' << 8), 62 + height * 4, 0, 0, 62 };
        //Header in datei schreiben:
        bmpfile << (char *)&BFHEADER;
        //hier folgen dann der BMP Info Header, die Farbtabelle usw...
    }
    

    Nun habe ich das Problem, dass wenn ich mir das ganze folgendermaßen ausgeben lassen, die
    Ausgabe so aussieht:

    BMÌÌR

    Das BM ist jedenfalls mal richtig, dannach, müsste aber direkt das R folgen (weil 82 Bytes für die
    Gesamtgröße der Datei in der ASCII Tabelle einem R entsprechen und direkt nach der Kennung BM folgen).
    Die beiden "ÌÌ" sind dabei jedoch sehr eigenartig. Im HexEdit betrachtet stehen diese als
    "cc" da. Ist das so eine Art Placeholder für nicht vollständig "ausgefüllte" Variablen? Eigentlich
    ist UINT16 ja schon genau die richtige Größe...!? Und das nächste ist, dass nach dem R ja noch ASCII Code
    für die Reservierten Bytes und die Zahl der Bytes vor Pixel Data folgen müssten...

    Kann mir jemand weiterhelfen oder sagen was ich falsch mache? Danke für alle Antworten

    Gruß

    Cyax


  • Mod

    ostream::operator<< für char* ist spezialisiert für Zeichenketten im C-Stil. Das heißt, es wird so lange geschrieben, bis das erste Zeichen mit dem Wert 0 auftaucht. Woher sonst sollte die Funktion wissen, wo das Ende ist? Bei dir sollte die erste 0 nach dem R kommen und tatsächlich hört dort das geschriebene auch auf. Benutz ostream::write, um Daten unformatiert zu schreiben.
    Die "Ì" sind wahrscheinlich Padding. Wenn man ein struct/class definiert, ist zwar garantiert, dass die Attribute alle in der Reihenfolge im Speicher liegen, wie man sie angegeben hat, aber es ist nicht garantiert, dass sie lückenlos im Speicher liegen. Es ist nämlich viel effizienter zum Rechnen, wenn das Programm die Felder an gewissen Grenzen im Speicher ausrichten kann (meistens Adressen, die genau durch 4 oder 8 teilbar sind). Wenn du garantieren möchtest, dass die structs lückenlos im Speicher liegen, musst du mal in der Anleitung deines Compilers gucken, ob es ein Feature gibt, dies zu erzwingen. Fast alle Compiler können das. Oft heißt es "pragma pack" oder ähnlich. Jedenfalls solltest du mit "pragma pack name_deines_compilers" etwas bei Google finden.
    Alternativ kannst du es auch einfach sein lassen, die Daten alle in einem Rutsch schreiben zu wollen und sie stattdessen einfach einzeln hintereinander ausgeben. Dann ist es egal, ob noch irgendwas zwischen den Daten steht, schließlich greifst du einzeln auf die jeweiligen Felder zu.



  • Hallo SeppJ,

    vielen Dank für deine ausführliche Antwort. Ich habe jetzt sowohl #pragma pack PACKED eingetragen
    als auch file.write(content, sizeof(content)) verwendet, es scheint jedenfalls zu funktionieren.
    Danke nochmal 😉 !

    Viele Grüße

    Cyax


Log in to reply