Header einer .bmp kopieren ...
-
Zur Übung haben wir gerade die Aufgabe bekommen, von einer vorgegebenen template.bmp den Header zu übernehmen, über Rekursion eine Koch-Kurve zu erzeugen und einzufügen und und das ganze dann als Koch.bmp zu speichern.
Ich hab hier zwar schon 3 Threads zum Thema header auslesen gefunden, aber ich finde nirgends was, wie man ihn einfach kopiert. Nachdem ich jetz fast nen ganzen Tag mit Google vergeudet hab (vielleicht hab ich auch die falschen Begriffe verwendet?), wär mal professionelle Hilfe nicht schlecht
Wär schön, wenn da jemand nen Link/Code hätte
Ps: Bin erst im 2. Semester, also mehr oder weniger Anfänger
-
Schau mal nach, wie lang so ein Header ist. Dann kannst du den einfach aus der Datei auslesen, in einen Buffer speichern und dann in die neue Datei rein schreiben. Danach schreibst du die Daten für deine Kurven.
-
zum aufbau einer bitmap:
da gehts zwar dann noch um pow aber ist ja egal, der aufbau der bmp ist wichtig.
-
Den Aufbau einer .bmp kenn ich. Die Befehle fürs auslesen sind mir auch geläufig, nur weiß ich eben nicht, wie man sie anwendet. Als erstes hätt ich folgendermaßen die Dateien geöffnet:
ifstream Original("template.bmp", ios::binary | ios::in); ofstream Koch("Koch-Kurve.bmp", ios::out | ios::binary);
Der Header besteht aus 54 Bytes. Gelesen hätt ich nun mit
Original.read(...)
Ich versteh aber nicht so ganz, wie man ein bestimmtes Byte liest. Ich dachte eigentlich immer, dass man eine Art Zeiger Byte für Byte weiterschieben kann und somit die Daten in ein Array/Buffer speichern kann. Aber scheinbar funktioniert das anders?
Was mir auch aufgefallen ist, dass manche beim lesen .read und manche .get verwenden. Genauso beim schreiben, .write oder .put. Wo liegt da der Unterschied ?
Unserer Professorin ist es leider immer etwas egal, ob unsere Kenntnisse ausreichen oder nicht.
-
schau mal da:
-
pippo schrieb:
Den Aufbau einer .bmp kenn ich. Die Befehle fürs auslesen sind mir auch geläufig, nur weiß ich eben nicht, wie man sie anwendet. Als erstes hätt ich folgendermaßen die Dateien geöffnet:
ifstream Original("template.bmp", ios::binary | ios::in); ofstream Koch("Koch-Kurve.bmp", ios::out | ios::binary);
Der Header besteht aus 54 Bytes. Gelesen hätt ich nun mit
Original.read(...)
Ich versteh aber nicht so ganz, wie man ein bestimmtes Byte liest. Ich dachte eigentlich immer, dass man eine Art Zeiger Byte für Byte weiterschieben kann und somit die Daten in ein Array/Buffer speichern kann. Aber scheinbar funktioniert das anders?
Was mir auch aufgefallen ist, dass manche beim lesen .read und manche .get verwenden. Genauso beim schreiben, .write oder .put. Wo liegt da der Unterschied ?
Unserer Professorin ist es leider immer etwas egal, ob unsere Kenntnisse ausreichen oder nicht.
Die ersten 54 Bytes kannst du so lesen:
char* buffer = new char[54]; binary_file.read(buffer ,54);
-
Hab heute mal noch nen Prof gefragt und das ganze erklärt bekommen, danke.
Im Moment hab ich aber doch noch 2 Probleme:
1. Gibt es einen Befehl, um die Anzahl der Pixel (Hoehe, Breite) zu bekommen? Wir haben nämlich folgendes bekommen:#pragma pack(1) struct bmInfoHeader { long biSize; // Laenge des Info Header long biWidth; // * Anzahl Pixel horizontal long biHeight; // * Anzahl Pixel vertikal short biPlanes; // muss eine 1 enthalten short biBitCount; // Anzahl Bits je Pixel, hier: 8 long biCompression; // hier: nicht komprimiert long biSizeImage; // Anzahl der Bytes fuer das Bild long biXPelsPerMeter; // hor. Aufloesung in Pixel/Meter long biYPelsPerMeter; // vert. Aufloesung in Pixel/Meter long biClrUsed; // Anzahl tatsaechlich benutzter Farben (0) long biClrImportant; // Anzahl unbedingt benoetigter Farben (0) }; struct bmFileHeader { // (includiert bmInfoHeader) char bfType1, bfType2; // dort steht 'B' 'M' long bfSize; // Dateilaenge short bfReserved1; short bfReserved2; long bfOffBits; // * Abstand zum Beginn der Bilddaten bmInfoHeader bmInfo; // der Info Header schliesst an };
Über sizeof(bmFileHEader) bekomm ich ja auch die Größe des Headers. Habs zwar jetz mit einer Vier-Byte-Umwandlung gemacht, aber das erscheint mir etwas umständlich.
2. In einer Funktion will ein dynamisches Array erstellen um alle Pixel dort zu speichern. Aber wie kann ich es anschließend der main übergeben? Sowas hatten wir bisher noch nicht
-
Schau dich hier im Forum mal etwas um. Unter anderem gibts hier was ähnliches, das dir helfen könnte:
http://www.c-plusplus.net/forum/viewtopic-var-t-is-105901.html
-
pippo schrieb:
2. In einer Funktion will ein dynamisches Array erstellen um alle Pixel dort zu speichern. Aber wie kann ich es anschließend der main übergeben? Sowas hatten wir bisher noch nicht
int* function(...) { ... return array; }
wobei:
int* array = new int[groesse];
zu 1.)
wenn der Header in einen char[] steht, und die größe z.B. ein int ist, welches vom 12-16 Byte geht:
int* size_x = (int*) &buffer[12]; cout << *size_x << endl;
-
@ Gast
Hab vergessen zu erwähnen, dass ich das mit einem 2-dimensionalen Array machen wollte. Aber wie ich mitlerweile herausgefunden habe, braucht man dazu ja einen vector. Kann dein letztes Beispiel denn eigentlich funktionieren? In muss die Bytes doch umwandeln, oder nicht?Hab mir jetz ne Header-Datei angelegt, die wie folgt aussieht:
#pragma pack(1) struct bmInfoHeader { long biSize; // Laenge des Info Header long biWidth; // * Anzahl Pixel horizontal long biHeight; // * Anzahl Pixel vertikal short biPlanes; // muss eine 1 enthalten short biBitCount; // Anzahl Bits je Pixel, hier: 8 long biCompression; // hier: nicht komprimiert long biSizeImage; // Anzahl der Bytes fuer das Bild long biXPelsPerMeter; // hor. Aufloesung in Pixel/Meter long biYPelsPerMeter; // vert. Aufloesung in Pixel/Meter long biClrUsed; // Anzahl tatsaechlich benutzter Farben (0) long biClrImportant; // Anzahl unbedingt benoetigter Farben (0) }; struct bmFileHeader { // (includiert bmInfoHeader) char bfType1, bfType2; // dort steht 'B' 'M' long bfSize; // Dateilaenge short bfReserved1; short bfReserved2; long bfOffBits; // * Abstand zum Beginn der Bilddaten bmInfoHeader bmInfo; // der Info Header schliesst an }; #pragma pack ()
... ifstream Original("template.bmp", ios::binary | ios::in); ofstream Koch("Koch-Kurve.bmp", ios::binary | ios::out); bmInfoHeader bIH; bmFileHeader bFH; // MAIN PROGRAM *************************************************************** int main() { char * Header = new char[sizeof(bmFileHeader)]; long Breite = bIH.biWidth, Hoehe = bIH.biHeight, Position; ... }
Wieso wird aber Breite und Hoehe auf 0 gesetzt? Muss man das ganze noch mit der Originaldatei verbinden? Dachte da wird automatisch die zum lesen geöffnete Datei genommen.
Was mich noch etwas verwundert: An der Position 10 steht als 4-Byte-Wert (1024) die Länge des Headers, bzw. die Position der Bilddaten. Jedoch beginnen die Pixel erst bei 1078. Was steht nun in den 54Bytes dazwischen? Konnte hierzu bisher nichts finden, obwohl ich mir schon einige Seite über den Aufbau einer .bmp durchgelesen hab
-
pippo schrieb:
@ Gast
Hab vergessen zu erwähnen, dass ich das mit einem 2-dimensionalen Array machen wollte. Aber wie ich mitlerweile herausgefunden habe, braucht man dazu ja einen vector. Kann dein letztes Beispiel denn eigentlich funktionieren? In muss die Bytes doch umwandeln, oder nicht?Binary file in 2D Array einlesen? Sorry, but sounds stupid to me. Du musst ERST das ganze Binary in einen char* (Array einlesen). Dann einen wasauchimmer2Darray für die Pixel reservieren.
Poste doch bitte mal ein wenig Code!
Generelles Vorgehen:
1.) Datei in char* lesen (wie oben beschrieben).
2.) Header aus dem char* extrahieren.
3.) Speicher für Pixel reservieren
4.) Pixel aus dem char* auslesen und in den Pixelspeicher schreibenWas mich noch etwas verwundert: An der Position 10 steht als 4-Byte-Wert (1024) die Länge des Headers, bzw. die Position der Bilddaten. Jedoch beginnen die Pixel erst bei 1078. Was steht nun in den 54Bytes dazwischen? Konnte hierzu bisher nichts finden, obwohl ich mir schon einige Seite über den Aufbau einer .bmp durchgelesen hab
k.A. Füllbytes? Wenn irgendwo steht, der Header einer BMP ist IMMER 1078 Bytes lang musst du die "Leerstelle" halt auffüllen.