integer-Array in bitmap-Bild speichern.



  • Ich möchte für ein Programm ein Array aus Integern in eine bitmap-Datei "umwandeln".

    Das Array ist etwa 500x500, aber kann auch größer/kleiner sein. Jeder Integer hat Wert 0 oder 1, wobei 0 -> weiss und 1 -> schwarz werden soll.

    Kann mir jemand erklären:

    1. Wie genau müssen Header, Farbtabelle, Pixelinformationen aussehen? Wiki hilft nicht wirklich weiter, da recht kompliziert, und besonders das mit der Farbtabelle erschliesst sich mir nicht.

    2. Die ersten beiden Bytes der Datei sollen wohl 0x42 0x4D sein (BM in Hexadezimal). Wie genau schreibe ich diese (und weitere) Bytes in eine Datei?

    FILE* output = fopen("output.bmp", "wb");
    

    Binärmodus ist klar, aber

    fprintf(output,"%d",0x42);
    

    wird wohl kaum stimmen...

    Wäre nett wenn mir da jemand ein Beispielt geben kann... in C++ gibt wohl fertige Funktionen für sowas, aber ich will C, und da gibt es natürlich keine vorgefertigten Klassen/Funktionen...

    Forensuche nach bitmap / BMP hat nichts sinnvolles ergeben...



  • Also dir hier das Bitmap-Format zu erklären, würde wohl niemand machen.
    Soviel ich noch weiß, hat das Format zu Beginn einen Infoblock konstanter Größe mit Formatinfos.
    Schreiben tust du einfach mit z.B.

    unsigned char header[345]={1,2,0xab,0xcd,0xef,...};
    unsigned char bild[500*500]={0,1,1,1,1,0,0,...};
    fwrite(header,sizeof header,1,output);
    fwrite(bild,500*500,1,output);
    


  • Ok, das war das größere Problem.

    struct bmpfile_magic {
      unsigned char magic[2];
    };
    
    struct bmpfile_header {
      uint32_t filesz;
      uint16_t creator1;
      uint16_t creator2;
      uint32_t bmp_offset;
    };
    
    typedef struct {
      uint32_t header_sz;
      uint32_t width;
      uint32_t height;
      uint16_t nplanes;
      uint16_t bitspp;
      uint32_t compress_type;
      uint32_t bmp_bytesz;
      uint32_t hres;
      uint32_t vres;
      uint32_t ncolors;
      uint32_t nimpcolors;
    } bmp_dib_v3_header_t;
    
    typedef enum {
      BI_RGB = 0,
      BI_RLE8,
      BI_RLE4,
      BI_BITFIELDS,
      BI_JPEG,
      BI_PNG,
    } bmp_compression_method_t;
    

    Das sind laut Wiki die Infos für den Header. Die sollte man dann ja einfach mit Daten füllen können, und dann per fwrite in die Datei tuen können. Stellt sich nur noch die Frage nach der Farbpalette: Hat da einer ein Beispiel, am besten eins mit nur Schwarz und Weiss? Laut Wiki muss da zb rein, dass wenn ich in den Bildinfos "1" schreibe, der da dann Schwarz draus macht (0,0,0) oder aus ner 0 (255,255,255)
    Oder Dateigröße ignorieren, und einfach jedes Pixel mit vollem RGB-Info? (Unten links anfangen ist mir klar) Geht laut Wiki ebenfalls 😃



  • Ich habe gerade eines 1000x1000 Pixels großes Schwarzweiß-Bild gemalt und als Monochrom-Bitmap abgespeichert. 128062 Bytes. Das ist fast genau 125000, was die reine Nutzlast wäre.



  • Wenn ich aber nur 1 Bit pro Pixel brauche (geht ja bei monochrom) wären es bei 1000x1000 ~62500 Byte (8 Bit = 1 Byte, oder? 😃 )

    Ist aber recht egal, ich gehe einfach von konstanter Größe aus, sonst müsste ich ja die Zahlen alle in Hex umwandeln, und dann auch noch in umgekehrter Reihenfolge ausgeben... 😃



  • Es tut mir leid, Dir die Wahrheit sagen zu müssen, aber Dein Taschenrechner ist kaputt. 🤡

    Ja, ein Byte pro Pixel wäre ein bißchen einfacher zu programmieren. Andererseits hat Monochrom bestimmt keine Paletten, ich dachte, vielleicht hebt sich das auf. 3 Byte haben mich so erschreckt. War ja nur ne Idee.



  • Ich kann davon ausgehen, dass die Breite ein Vielfaches von 4 ist, also muss ich ja nichts auffüllen beim schreiben. Jetzt habe ich mir mal aufgeschrieben, wie der Header auussehen muss, und laufe dann das Array einfach durch. Sollte dann ja gehen, denke ich. Eigentlich ist Dateigröße auch egal, aber ich dachte wenn man schon C macht, kann man auch optimieren...

    Also, ich versuche grade die Datei zu schreiben:

    42 4D // Sind die ersten Byte, stehen für BM, muss wohl rein?
    C0 A8 00 00 // Größe der Datei (800x600 Pixel, 24 Bit = 3 Byte pro Pixel, plus 54 Byte Header
    00 00 //hängt davon ab, welches programm das bild baut -> wayne
    00 00 //hängt davon ab, welches programm das bild baut -> wayne
    36 00 00 00 // wie weit weg die bildinfos sind
    28 00 00 00 // wieviele bytes noch im header sind.
    20 03 00 00 // breite 800 in hex, unwichtigste stelle zuerst (mag mich hier irren)
    58 02 00 00 // höhe 600 in hex, unwichtigste stelle zuerst (mag mich hier irren)
    01 00 // anzahl farbebenen
    18 00 // bits pro pixel
    00 00 00 00 // keien kompression, RGB
    F6 A8 00 00 // größe der bildinformationen... 800x600x3 byte
    13 0B 00 00 // horizontale auflösung
    13 0B 00 00 // vertikale auflösung
    00 00 00 00 // anzahl farben in palette (habe keine)
    00 00 00 00 // alle farben sind wichtig

    Vergleiche hierzu: http://en.wikipedia.org/wiki/BMP_file_format#Example_of_a_2x2_Pixel.2C_24-Bit_Bitmap

    Dann gehe ich die Pixel durch, und falls es Schwarz ist, schreibe ich 00 00 00, wenns weiss ist schreibe ich FF FF FF. Jeweils alles als unsigned char Array. Wenn ich das ganze Array in die Datei tuen will, muss ich dann Länge 1 oder Länge des Arrays für write() nehmen?

    Ach ja, es geht übrigens nicht, die BMP ist nicht zu öffnen... Kennt sich da einer mit aus? 😃



  • Wieso verwendest du nicht einfach eine fertige Bibliothek.

    z.B. libbmp

    http://crococode.free.fr/pages/prg_graphic.php
    ansonsten kann dir zumindest der Sourcecode behilflich sein.

    oder nachdem du eh nur schwarz/weiß verwendet nicht ein anderes Grafikformat.
    z.B. pgm (Portable Graymap)
    hier ist der Dateiaufbau wesentlich einfacher bzw. kann über die iLib
    http://www.k5n.us/Ilib.php
    vorgenommen werden.


Anmelden zum Antworten