In BMP-Datei schreiben
-
Moin,
ich hab da ein kleines Problem mit meinem Programm, das eine BMP Datei mit 640*480 Pixeln schreiben soll. Hier erstmal der Code:#include <fstream> #include <ctime> #include <windows.h> using namespace std; struct BMPHEADER { SHORT id; //BMP-File ID "BM" DWORD size; //Größe der Datei DWORD res1; //reserviert DWORD res2; DWORD BMPdata; //Offset vom Programmanfang zu Bilddaten }; struct INFHEADER { DWORD biSize; //Strukturgröße von BMPHEADER DWORD biWidth; //Breite des Bildes DWORD biHeigth; //Höhe des Bildes WORD biPlanes; //"Zeichenebenen" WORD biBitCount; //Farbtiefe DWORD comp; //Kompression DWORD SizeImage; //Größe der Bilddaten in Byte DWORD XPixelperMeter; //nicht notwendig (=0) DWORD YPixelperMeter; //ebenso DWORD ClrUsed; //verwendete Farben DWORD ClrImportant; //wichtige Farben(0: alle Farben wichtig) }; BMPHEADER bmpfheader = {19778,sizeof(BMPHEADER)+sizeof(INFHEADER)+3*(640*480), 0,0,sizeof(BMPHEADER)+sizeof(INFHEADER)}; //19778 //bezeichnet "BM" Kennung, Offsetangabe so ok? INFHEADER infhead = {sizeof(BMPHEADER),640,480,0,24,0,640*480*3,0,0,0,0}; char Array[640][480][3]; //640*480 Pixel, 3Byte pro Pixel int main() { srand(time(0)); for(int i= 0; i<100;i++) { for(int k=0;k<100;k++) { for(int j=0;j<3;j++) { Array[i][k][j] = rand()%256; //Fülle Pixel mit Zufallswerten } } } ofstream Bild("hallo.bmp", ios::out|ios::binary|ios::trunc); Bild.write(reinterpret_cast<char*>(&bmpfheader), sizeof(BMPHEADER)); Bild.write(reinterpret_cast<char*>(&infhead), sizeof(INFHEADER)); Bild.write(reinterpret_cast<char*>(Array),3*(640*480)); Bild.close(); return 0; }Ich hab mich hier vorerst auf 24-Bit-Farbtiefe beschränkt, da die eigentlichen Bilddateien direkt hinter dem INFHEADER folgen und keine Farbpalette benötigt wird. Der Code selbst lässt sich wunderbar kompilieren, nur die geschriebene BMP-Datei lässt sich nicht Öffnen("Error Opening this document"). Ich bin der BMP-Datei auch schon mit dem Hexeditor zu Leibe gerückt, die "BM" Kennung am Anfang schreibt er jedenfalls ordentlich rein. Ich habe auch schon probiert mit #pragma pack(0) das Alignment auszuschalten, aber das hat auch nicht geholfen. Sieht vielleicht jemand, was ich falsch mache?
-
Matzer schrieb:
Ich habe auch schon probiert mit #pragma pack(0) das Alignment auszuschalten, aber das hat auch nicht geholfen. Sieht vielleicht jemand, was ich falsch mache?
pack(0) ist ja auch Quatsch. Mein Compiler sagt dazu:
warning C4086: expected pragma parameter to be '1', '2', '4', '8', or '16'
-
Du hast den Bitmap-Header nicht wirklich korrekt zusammengesetzt:
Matzer schrieb:
struct BMPHEADER { SHORT id; //BMP-File ID "BM" DWORD size; //Größe der Datei DWORD res1; //reserviert DWORD res2; DWORD BMPdata; //Offset vom Programmanfang zu Bilddaten };Das DWORD res2 ist überflüssig - und zerstört in der Folge auch die Offset-Berechnungen.
struct INFHEADER { DWORD biSize; //Strukturgröße von BMPHEADER DWORD biWidth; //Breite des Bildes DWORD biHeigth; //Höhe des Bildes WORD biPlanes; //"Zeichenebenen" WORD biBitCount; //Farbtiefe DWORD comp; //Kompression DWORD SizeImage; //Größe der Bilddaten in Byte DWORD XPixelperMeter; //nicht notwendig (=0) DWORD YPixelperMeter; //ebenso DWORD ClrUsed; //verwendete Farben DWORD ClrImportant; //wichtige Farben(0: alle Farben wichtig) };biWidth und biHeigth sind LONG-Werte (letzteres kann auch negativ werden), genauso die beiden PxielperMeter-Werte.
BMPHEADER bmpfheader = {19778,sizeof(BMPHEADER)+sizeof(INFHEADER)+3*(640*480), 0,0,sizeof(BMPHEADER)+sizeof(INFHEADER)}; //19778 //bezeichnet "BM" Kennung, Offsetangabe so ok?Abgesehen davon, daß eine 0 zu viel ist (siehe oben), sieht die Angabe gut aus.
INFHEADER infhead = {sizeof(BMPHEADER),640,480,0,24,0,640*480*3,0,0,0,0};falscher Größenwert (du brauchst 'sizeof(INFHEADER)'), biPlanes sollte 1 sein - und für die Datengröße kannst du auch 0 einsetzen.
char Array[640][480][3]; //640*480 Pixel, 3Byte pro PixelDer Platz reicht zwar, aber ich bin mir jetzt nicht ganz sicher, ob die Anordnung zum Bitmap passt.
-
Vielen Dank für die Hinweise, hat wunderbar geklappt. Ich stell den (funktionierenden) Source hier nochmal rein, vielleicht kann es ja jemand gebrauchen:
#include <fstream> #include <ctime> #include <windows.h> using namespace std; #pragma pack(1) struct BMPHEADER { SHORT id; DWORD size; DWORD res1; DWORD adress_BMP_data; }; struct INFHEADER { DWORD biSize; LONG biWidth; LONG biHeigth; WORD biPlanes; WORD biBitCount; DWORD comp; DWORD SizeImage; LONG XPixelperMeter; LONG YPixelperMeter; DWORD ClrUsed; DWORD ClrImportant; }; BMPHEADER bmpfheader = {19778,sizeof(BMPHEADER)+sizeof(INFHEADER)+3*(640*480), 0,sizeof(BMPHEADER)+sizeof(INFHEADER) }; INFHEADER infhead = {sizeof(INFHEADER),640,480,1,24,0,640*480*3,0,0,0,0}; char Array[640][480][3]; int main() { srand(time(0)); for(int i= 0; i<640;i++) { for(int k=0;k<480;k++) { for(int j=0;j<3;j++) { Array[i][k][j] = rand()%256; } } } ofstream Bild("hallo.bmp", ios::out|ios::binary|ios::trunc); Bild.write(reinterpret_cast<char*>(&bmpfheader), sizeof(BMPHEADER)); Bild.write(reinterpret_cast<char*>(&infhead), sizeof(INFHEADER)); Bild.write(reinterpret_cast<char*>(Array),3*(640*480)); Bild.close(); return 0; }
-
Wow, so eine schönes Bild hatte ich ja noch nie...