erstellen eines BMP



  • Also zuerst einmal ist da die Frage, ob die Datei mit dem Modus binär geöffnet wird.
    Ich würde es auch nicht Elementweise mit << schreiben, sondern
    a) Mir einen entsprechend großen Speicherbereich erstellen.
    b) In diesem Speicher dann das Bitmap komplett mit Header erstellen.
    (dazu muss man aber fit sein in Sachen Pointer)
    c) alles in einem Rutsch schreiben mit write.

    So kannst du vor dem Speichern im Debugger schön den Speicher betrachten und hast so die Gewissheit, dass es dann auch so in die Datei geschrieben wird.



  • Deine Speicherreservierung für die Pixel ist auch nicht so schön und schreit förmlich nach Speicherlecks.
    Zumal dir die WinAPI ja schon die passende struct liefert.
    Du musst nicht Zeilenweise reservieren, sondern kannst auch alles auf einmal bestellen.

    RGBQUAD *pPixels = new RGBQUAD(Höhe*Breite);
    ...
    delete[] pPixels;
    

    Das schöne ist, dass hierbei gleich gewährleistet ist, dass an 4 Byte ausgerichtet wird, da ja die struct eben so groß ist.



  • okay. ich bearbeite mal deine vorschläge. wenn's immer noch nicht klappt, melde ich mich noch einmal.

    an sich ist es doch aber nicht falsch, wenn ich

    myfile << IRGENDWAS;
    

    verwende, richtig?
    DANKE.



  • Wenn für IRGENDWAS der ofstream<< Operator richtig überladen ist, ist alles in Ordnung.
    Außerdem musst man hier halt immer aufpassen, dass man die richtige Reihenfolge einhält.
    Und sowas wie du da gemacht hast, einfach mal was auskommentieren, geht da natürlich schon mal gar nicht.

    Weißt du, es gibt einfach Fälle, da ist es besser Daten hintereinander zu schreiben wie am Fließband. Z.B. wenn man das Alphabet ausgeben möchte. Dann nimmt man die stream << Dinger und schickt in einer Schleife alle Buchstaben raus.

    Und es gibt Fälle, da will man seine Daten im Speicher erst aufbereiten, wie halt du mit den Pixeln und dem Header.
    Und dann schreibt man alles als größen Block in einem Stück.



  • also,

    ich habe den code jetzt deinen vorschlägen angepasst (abgesehen von dem "entsprechend großen Speicherbereich" ), aber leider hauts noch nicht hin. könnte das an "bmfh.bOffBits" liegen? warum gibts damit probleme?

    welchen typ sollte der grosse speicherbereich haben? ist es BYTE?

    DANKE.
    STICK.



  • Poste mal deinen überarbeiten Code.



  • hier kommt er schon.

    #include <iostream.h>
    #include <fstream.h>
    #include <windows.h>
    
    int main ()
    {
    	ofstream		myfile;
    	BITMAPFILEHEADER	bmfh;
    	BITMAPINFOHEADER    bmih;
    	int			i,j;
    	RGBQUAD			*pPixels = new RGBQUAD [8*8];
    
    	for (i=0;i<64;i++)
    	{
    		pPixels[i].rgbBlue = (BYTE)i;
    		pPixels[i].rgbGreen= (BYTE)i;
    		pPixels[i].rgbRed  = (BYTE)i;
    		pPixels[i].rgbReserved=(BYTE)0;
    	}
    
    	bmfh.bfType		= 0x4D42;
    	bmfh.bfSize		= 296; // = 8*8*(4) + 40 (für header) >> ist es 8*8*3 oder 8*8*4 ???
    	bmfh.bfReserved1	= 0;
    	bmfh.bfReserved2	= 0;
    //	bmfh.bOffBits		= 0;
    
    	bmih.biSize		= 40;
    	bmih.biWidth		= 16;
    	bmih.biHeight		= -16;
    	bmih.biPlanes		= 1;
    	bmih.biBitCount		= 24;
    	bmih.biCompression	= 0;
    	bmih.biSizeImage	= 0;
    	bmih.biXPelsPerMeter= 0;
    	bmih.biYPelsPerMeter= 0;
    	bmih.biClrUsed		= 0;
    	bmih.biClrImportant	= 0;
    
    	myfile.open("test.bmp",ios::out);
    	myfile<<bmfh.bfType<<" "<<(BYTE)bmfh.bfSize<<" "<<(BYTE)bmfh.bfReserved1<<" "
    		  <<(BYTE)bmfh.bfReserved2<</*" "<<(BYTE)bmfh.bOffBits<<*/"\n";
    	myfile<<(BYTE)bmih.biSize<<" "<<(BYTE)bmih.biWidth<<" "<<(BYTE)bmih.biHeight<<" "
    		  <<(BYTE)bmih.biPlanes<<" "<<(BYTE)bmih.biBitCount<<" "<<(BYTE)bmih.biCompression<<" "
    		  <<(BYTE)bmih.biSizeImage<<" "<<(BYTE)bmih.biXPelsPerMeter<<" "<<(BYTE)bmih.biYPelsPerMeter<<" "
    		  <<(BYTE)bmih.biClrUsed<<" "<<(BYTE)bmih.biYPelsPerMeter<<"\n";
    
    	j=0;
    	for (i=0;i<64;i++)
    	{
    		if (j==8)
    		{
    			myfile << pPixels[i].rgbBlue << " " << pPixels[i].rgbGreen    << " " 
    				   << pPixels[i].rgbRed  << " " << pPixels[i].rgbReserved << "\n";
    			j=0;		
    		}
    
    		else
    		{
    			myfile << pPixels[i].rgbBlue << " " << pPixels[i].rgbGreen    << " " 
    				   << pPixels[i].rgbRed  << " " << pPixels[i].rgbReserved;
    			j++;
    		}
    	}
    
    	delete[] pPixels;
    	myfile.close();
    
    	return 0;
    }
    


  • Die Sache mit dem Pixelarray sieht schon mal gut aus,
    aber kannst du mir mal verraten, was die Sache mit dem Newline soll?
    Was hat ein Newline in einer Binärdatei zu suchen?

    Du hast doch mit pPixels schon ein schönes Array, das kannst du doch nun bequem schreiben mit write.
    Was soll die Verrenkung mit der Schleife.



  • Und die Sache mit dem bmfh.bOffBits ist dazu da, dass angegeben wird, wo die Pixeldaten in der Datei anfangen.

    Nehmen wir mal an, der Header sei 100 Bytes groß, dann beginnen die Pixeldaten an Position 100.

    EDIT: Für bfSize nimmst du den Speicherverbrauch von einem Pixel, der beträgt 4 Byte.



  • - die verrenkung mit der schleife habe ich, damit ich die einzelnen pixelelemente, die sich in dem array pPixels befinden, ansprechen kann, aber vielleicht sollte ich mir mal die funktion WRITE anschauen.
    - wenn ich keine newline habe, woher weiss ein program wie PHOTOSHOP dann, wann eine neue zeile im bild kommt?
    - was "bmfh.bOffBits" bedeutet, ist mir bereits klar. aber warum sagt mein programm andauernd, dass es kein element von BITMAPFILEHEADER ist?



  • Vermutlich weil es bfOffBits heißt und nicht bOffBits.

    Photoshop weiß es deshalb, weil es weiß, dass das Bild 8 Pixel breit ist, weil
    in biWidth (hoffentlich) der richtige Wert steht.



  • nochmal kurz. wir bekomme ich die grösse meine pPixels arrays heraus? das brauche ich ja für die WRITE funktion.

    so klappts jedenfalls nicht:

    myfile.write(pPixels,64);
    


  • Du kannst schon die Größe mit 64 Angeben.
    Aber der erste Parameter muss nach const char* gecastet werden, weil
    write das 1. Argument so erwartet.

    myfile.write((const char*) pPixels, 64);



  • HALLO.
    kannst du dir bitte noch einmal diesen code anschauen? dazu hätte ich folgende fragen:

    1.) wenn ich die header infos in die bitmap datei eintrage, ohne pixel dateien, ist die grösse der datei 40 BYTE. was ist da noch falsch (sollte doch 54 sein)? ich vermute, dass ich nicht alle in BYTE verwandeln sollte, oder?
    oder kommt jetzt deine befürchtung zum tragen, dass ich nicht "myfile << Irgendetwas;" verwenden sollte?

    2.) angenommen, ich lasse dann den headerfile weg. warum ist die datei dann nur 64 BYTE gross, wenn ich "myfile.write" nutze, aber 256 BYTE, wenn ich die for-schleife einsetze? ich denke, ich muss anstatt von 16 die zahl 256 (also 4*64) einsetzen.

    3.) welchen datentyp sollte das ARRAY haben, wenn ich dort alle daten (header- und pixelinfo) reinschreiben möchte?

    ...
    	bmfh.bfSize		= 310; // mit oder ohne HEADER (14+40)?
        ...
    	bmfh.bfOffBits		= 55; // ist das okay so?
        ...
        myfile.open("test.bmp",ofstream::binary); //sollte nun ne binärdatei sein, richtig?
    	myfile<<(BYTE)bmfh.bfType
    		  <<(BYTE)bmfh.bfSize<<(BYTE)bmfh.bfReserved1
    		  <<(BYTE)bmfh.bfReserved2<<(BYTE)bmfh.bfOffBits
    		  <<(BYTE)bmih.biSize<<(BYTE)bmih.biWidth<<(BYTE)bmih.biHeight
    		  <<(BYTE)bmih.biPlanes<<(BYTE)bmih.biBitCount<<(BYTE)bmih.biCompression
    		  <<(BYTE)bmih.biSizeImage<<(BYTE)bmih.biXPelsPerMeter<<(BYTE)bmih.biYPelsPerMeter
    	      <<(BYTE)bmih.biClrUsed<<(BYTE)bmih.biYPelsPerMeter;
    
    /*
    	for (i=0;i<64;i++)
    	{
    		myfile << pPixels[i].rgbBlue 
    			   << pPixels[i].rgbGreen
    			   << pPixels[i].rgbRed
    			   << pPixels[i].rgbReserved;
    	}
    */
    	myfile.write((const char*) pPixels, 256);
    

    DANKE NOCHMALS.
    STICK.



  • hi.

    no@one schrieb:

    Schau mal hier nach:
    http://easybmp.sourceforge.net/

    ich habe mir das heute mal angeschaut. nun habe ich feststellen müssen, dass mit dieser library alles viel einfacher geht und man sich ne ganze menge code ersparen kann.

    so siehts nämlich jetzt aus:

    #include <EasyBMP.h>
    
    int main ()
    {
    	BMP AnImage;
    	int i,j;
    
    	AnImage.SetSize(16,16);
    	AnImage.SetBitDepth(24);
    
    	for (i=0;i<16;i++)
    	{
    		for (j=0;j<16;j++)
    		{
    			AnImage(i,j)->Red   = 10;
    			AnImage(i,j)->Green = 20;
    			AnImage(i,j)->Blue  = 30;
    			AnImage(i,j)->Alpha   = 0;
    		}
    	}
    	AnImage.WriteToFile("test.bmp");
    
    	return 0;
    }
    

    darum werde ich wahrscheinlich damit weiterarbeiten.
    STICK.


Anmelden zum Antworten