Problem mit bmp-Format
-
Ein Problem, das jetzt schon ins Auge sticht - op<< schreibt die int-Werte in Textform in die Datei, BMP braucht diese Angaben aber in Binärformat (dazu müsstest du die Daten per write() schreiben).
PS: Für die Header-Informationen kannst du auch die MS-Klassen BITMAPHEADER und BITMAPINFOHEADER verwenden

-
Das mit dem Operator << ist ein guter Tip, danke.
Das mit der Klasse wäre mein nächster Schritt gewesen, ich wollte es nur erstmal "von Hand" probieren.
Alles klar, danke!
-
good luck
greetz, Swordfish
PS: Vielleicht magst Du uns dann das Endresultat als Klasse bestaunen lassen?
-
Würd ich gerne machen, nur erstmal muss ich dahinter kommen, warum das ganze nit läuft...

#include <cstdio> #include <ctime> #include <cstdlib> int main() { FILE *f = fopen("D:\\Eigene~1\\f.bmp", "wb"); //header fprintf(f, "%c%c", 'B', 'M'); fprintf(f, "%lu%lu%lu", 30000, 0, 52); //infoheader fprintf(f, "%lu%ld%ld", 40, 100,100); fprintf(f, "%hu%hu%lu%lu", 1, 24, 0, 0); fprintf(f, "%ld%ld%lu%lu", 0, 0, 0, 0); //body srand(time(0)); for(unsigned register int t = 0; t < 30000; ++t) { fprintf(f, "%c", rand()%256); } return 0; }Ich hab irgendwo gelesen, dass man jede Zeile mit Nullern auffüllen muss, nur hab ich bei dem Artikel auf Wiki nicht ganz geblickt, wie genau.
Weiss jemand genaueres darüber?Danke schonmal!
-
wenn ich so ein programm schreiben würde, würde ich mir doch erstma angucken, wie meine erzeugte datei aussieht. zB mit Totalcommander oder einem hexeditor.
Und den HEader vergleichen mit einem funktionierendem Bitmap. Dann weißt du wo der Fehler in deiner Datei lioegt und du kannst demensprechend rangehen.btw., meiner meinung nach schreibt auch fprintf ascii-text und keine binärdaten in die Datei... hättest du dir die datei angeguckt, wüsstest du das jetzt auch.
nimm std::ofstream mit std::ofstream::write() zum binärdaten schreiben
-
Yippie!
Danke für den Tip, dachte fprintf würde mir die Arbeit abnehmen...

Naja, hier mal der Code:
#include <iostream> #include <fstream> #include <ctime> using namespace std; template <class T> void writeBin(fstream &Out, T data) { if(Out) { Out.write(reinterpret_cast<char*> (&data), sizeof(T)); } else { cout<<"Error: passed fstream is not open."<<endl; } } int main() { fstream data("D:\\Eigene~1\\f.bmp", ios::out | ios::trunc | ios::binary); writeBin(data, 'B'); writeBin(data, 'M'); writeBin(data, 30000); writeBin(data, 0); writeBin(data, 52); writeBin(data, 40); writeBin(data, 100); writeBin(data, 100); writeBin(data, (short) 1); writeBin(data, (short) 24); writeBin(data, 0); writeBin(data, 0); writeBin(data, 0); writeBin(data, 0); writeBin(data, 0); writeBin(data, 0); srand(time(0)); for(unsigned register int t = 0; t < 30000; ++t) { writeBin(data, (char) rand()%256); } return 0; }
-
template <class T> bool writeBin(std::ofstream &out, T& data) { if (out.good() == false || out.is_open() == false) { std::cout << "ERROR: Passed filestream is not open!" << std::endl; return false; } out.write(reinterpret_cast<char*>(&data), sizeof(T)); if (out.bad() == true) { std::cout << "ERROR: An error has occurred during reading data!" << std::endl; return false; } return true; }So hast de wenigstens einigermaßen Sicherheit, dass das in Ordnung geht

Hmm und warum legst du dir nicht eine Bitmap Strukt usw an die du dann am Anfang mit Werten füllst und dann am Ende einfach nur noch reinschreibst?
-
Hm, is_open hieß das... (Ich habs mit isOpen versucht und mich gewundert, warum das ganze nicht gelaufen ist
)Stimmt, ne Struct wäre auch einen Idee... *Anfängerbin*
Dumm-di-dumm, mache mich an die Arbeit mit der Klasse...
-
Hi!
Vieleicht kann ich dir ja hiermit helfen.
Ich habe vor einiger Zeit eine kleine BMP-Klasse geschrieben, vieleicht kannst du damit ja was anfangen:http://www.hooster.de/BmpClass.zip
Es sind in dem Paket 2 Beispielprojekte. Das erste Projekt (BMPCreate) erstellt ein 500x500 Pixel großes BMP-Bild mit Zufallswerten (Augenkrebs anyone?
).
Das zweite Projekt (BMPGrey) ist schon etwas Produktiver und zerlegt ein RGB-Bild in seine 3 Kanäle (Rot + Grün + Blau) und erstellt noch das dazugehörige Grautonbild.
Der Quellcode ist nicht Kommentiert. Die Funktionen der Klasse sollten selbsterklärend sein, das was drinnen ist müsstest du mal schauen ob du daraus schlau wirst
Ach so und die Klasse unterstützt keine RLE-Komprimierten BMP-Bilder.Grüße
FloFri
-
Danke für den Code!
So ähnlich hatte ich mir das vorgestellt, nur dass meine Klasse nicht bereits bmp24 sein soll, sondern eine generelle Bild-Klasse, die dann verschiedene Exportfunktionen besitzt (z.B. Picture::to24bmp oder Picture::toJpeg oder ähnlich). Außerdem würd ich gern ein paar simple Bearbeitungsfunktionen einbauen, sowas wie Linien ziehen oder so.
*freu*
-
schau mal nach CxImage: http://www.codeproject.com/bitmap/cximage.asp
-
Hm.. Danke für den Link, allerdings will ich eigentlich meinen Code selbst "erfinden"

Ich bin schon recht weit mit meiner Klasse, nur bin ich auf Probleme gestoßen:
1. Wenn ich ein pic als 24bmp exportiere, sieht das mit MSPaint aus, wie es aussehen sollte, und mit der XP-Standardanzeige sind Blau und Grün vertauscht...
2. Wenn ich jedem Pixel einzeln seinen Wert zuweise bekomme ich ein seltsames Muster, wenn ich das per Konstruktor mache (siehe Code) ist alles einfarbig, wie es sein sollte...Hier der Code:
#ifndef PIC_H_INCLUDED #define PIC_H_INCLUDED struct Pixel { char R; char G; char B; }; class Picture { Pixel *pix; long x; long y; public: Picture() { pix = 0; x = 0; y = 0; } Picture(long a,long b) { pix = new Pixel[a*b]; x = a; y = b; } Picture(long,long, char,char,char); //Um diesen Konstruktor geht's ~Picture() { delete [] pix; } void setdimension(long, long); void setwidth(long); void setheight(long); long getwidht(); long getheight(); void setPixel(long,long, char,char,char); //Und hiermit: seltsames Muster (siehe main.cpp) Pixel getPixel(long,long); char getR(long,long); char getG(long,long); char getB(long,long); void line(long,long, long,long); void to24Bmp(char*); }; #endif#include <iostream> #include <fstream> #include <cstdlib> #include "pic.h" using namespace std; template <class T> void writeBin(fstream &Out, T data) { Out.write(reinterpret_cast<char*> (&data), sizeof(T)); } Picture::Picture(long a,long b, char R,char G,char B) { if(a < 0 || b < 0 || a > 10000 || b > 10000) { cout << "error: dimensions are too big / below zero"; exit(-1); } unsigned register long i; pix = new Pixel[a*b]; x = a; y = b; for(i = 0; i < a*b; ++i) { pix[i].R = R; pix[i].G = G; pix[i].B = B; } } void Picture::setPixel(long a,long b, char R,char G,char B) { pix[a*b].R = R; pix[a*b].G = G; pix[a*b].B = B; } Pixel Picture::getPixel(long a,long b) { return pix[a*b]; } char Picture::getR(long x,long y) { return pix[x*y].R; } char Picture::getG(long x,long y) { return pix[x*y].G; } char Picture::getB(long x,long y) { return pix[x*y].B; } void Picture::to24Bmp(char *filename) { unsigned register long i; fstream data(filename, ios::out | ios::binary | ios::trunc); if(!data.is_open() || data.bad()) { cout << "error: cannot open file" << endl; exit(-1); } writeBin(data, 'B'); writeBin(data, 'M'); writeBin(data, (long) x*y*3+52); writeBin(data, (long) 0); writeBin(data, (long) 52); writeBin(data, (long) 40); writeBin(data, x); writeBin(data, y); writeBin(data, (short) 1); writeBin(data, (short) 24); writeBin(data, (long) 0); writeBin(data, (long) 0); writeBin(data, (long) 0); writeBin(data, (long) 0); writeBin(data, (long) 0); writeBin(data, (long) 0); for(i = 0; i < x*y; ++i) { writeBin(data, pix[i]); } }#include <iostream> #include "pic.h" using namespace std; int main() { unsigned register long i; Picture p(100,100); for(i = 0; i < 10000; ++i) { p.set(i%100, i/100, 0,255,0); // ??? } p.to24Bmp("D:\\Eigene~1\\f.bmp"); return 0; }Danke für die Hilfe! Und sorry, dass ich jetzt den kompletten Code reingepostet hab...