Erzeugung einer Graphikdatei mit C++



  • Hallo liebe Community,

    ich stehe bei der Programmierung eines Projekts vor einer Huerde, zu deren Loesung mir momentan nichts einfaellt und bei der ich fuer Loesungsideen dankbar waere.
    Konkret geht es um Folgendes: Ich beschaeftige mich zur Zeit mit duenn besetzten Matrizen und wuerde in mein Projekt gerne ein Tool integrieren, dass fuer eine konkrete, gegebene Matrix den Besetzungsgraphen als Datei erzeugt.
    Dabei sollen besetzte Eintraege (!=0) einfach schwarz und leere (=0) weiss erscheinen.
    Ich koennte mir vorstellen, sowas als .bmp oder so zu erzeugen, wo man die einzelnen Pixel direkt ansteuern kann. Die Frage ist dann aber, wie man so etwas macht.
    Ich waere fuer ein paar Ideen dankbar,

    Daramos



  • a) benutze dafür eine Bibliothek die dir all das abnimmt und wo du stumpf Pixel ansprechen kannst
    b) schau dir die Definition der jeweiligen Bildformate an und schreib das so raus in eine Datei (.bmp ist da wohl mit am einfachsten)



  • Probier's mal mit libpng + png++. Ist zumindest unter Linux super einfach.



  • Danke erstmal euch beiden fuer die Tipps. An eine Bibliothek hatte ich auch schon gedacht. Ich programmiere allerdings unter Windows mit dem Code Gear RAD Studio. Gibt es vielleicht zu der Linux-Bibliothek ein Windows-Aequivalent?


  • Administrator

    Daramos schrieb:

    Gibt es vielleicht zu der Linux-Bibliothek ein Windows-Aequivalent?

    libpng ist plattformunabhängig. Sollte somit auch unter Windows funktionieren. Und da png++ nur ein Wrapper ist, sollte dieser wohl auch unter Windows funktionieren 😉

    Grüssli



  • Dafür brauchst du nicht einmal externe Bibliotheken, das kannst du über die Klasse TBitmap erledigen:

    boost::shared_ptr<Graphics::TBitmap> Bitmap( new Graphics::TBitmap() );
    Bitmap->PixelFormat   = pf32bit;
    Bitmap->Width         = Width;
    Bitmap->Height        = Height;
    
    if( Bitmap->Canvas->Pixels[0][0] == clBlack )
    {
       Bitmap->Canvas->Pixels[0][0] = clWhite;
    }
    Bitmap->SaveToFile( "c:/bitmap.bmp" );
    

  • Administrator

    DocShoe schrieb:

    Dafür brauchst du nicht einmal externe Bibliotheken, das kannst du über die Klasse TBitmap erledigen:

    Witzbold! TBitmap ist kein Standard C++. TBitmap kommt von einer externen Bibliothek nämlich VCL.

    Grüssli



  • Dravere schrieb:

    DocShoe schrieb:

    Dafür brauchst du nicht einmal externe Bibliotheken, das kannst du über die Klasse TBitmap erledigen:

    Witzbold! TBitmap ist kein Standard C++. TBitmap kommt von einer externen Bibliothek nämlich VCL.

    Grüssli

    Daramos schrieb:

    Danke erstmal euch beiden fuer die Tipps. An eine Bibliothek hatte ich auch schon gedacht. Ich programmiere allerdings unter Windows mit dem Code Gear RAD Studio. Gibt es vielleicht zu der Linux-Bibliothek ein Windows-Aequivalent?

    Selber Witzbold! 😃


  • Administrator

    DocShoe schrieb:

    Daramos schrieb:

    Danke erstmal euch beiden fuer die Tipps. An eine Bibliothek hatte ich auch schon gedacht. Ich programmiere allerdings unter Windows mit dem Code Gear RAD Studio. Gibt es vielleicht zu der Linux-Bibliothek ein Windows-Aequivalent?

    Selber Witzbold! 😃

    Ehm, dir ist aber schon klar, dass die VCL trotzdem eine externe Bibliothek ist? Und zwar eine verdammt grosse, ein absolutes Schwergewicht! libpng ist da im Vergleich mikrig.

    Übrigens, wieso legst du TBitmap auf dem Heap an? 😕

    Grüssli



  • Wenn man das so pedantisch sieht hast du natürlich recht, aber bevor ich eine weitere Abhängigkeit in meine Projekte einführe benutze ich doch lieber das, was die Compilersuite von sich aus mitbringt.
    Leider kann man nichts, was TObject als Basisklasse hat, auf dem Stack erzeugen, und leider gehört TBitmap auch zu den TObject Derivaten. Ist ein "Feature" der VCL, das ich über alles schätze... naja, immerhin hat mich dieser Sachverhalt auf boost aufmerksam gemacht.



  • Hallo DocShoe,

    das sieht sehr nach etwas aus, das mir hilft. Dankeschoen!
    Leider hab ich bisher kaum mit Bibliotheken und Templates gearbeitet und bin mir deshalb nicht ganz sicher, was dein Code-Vorschlag tut.
    Ich hab mal versucht, in einzubauen, und ihn leicht veraendert.
    Matrix ist die Klasse, in der die Bitmap-Erzeugungsroutine liegen soll, cols und rows sind Spalten und Zeilen der Matrix.
    Die Pixel sollen dann entsprechend den Matrixeintraegen weiss oder schwarz gefaerbt werden.

    void Matrix::plot() const
    {
    boost::shared_ptr<Graphics::TBitmap> Bitmap(new Graphics::TBitmap);
    Bitmap->PixelFormat   = pf32bit;
    Bitmap->Width         = cols;
    Bitmap->Height        = rows;
    
    for (int i = 0; i < rows; i++) {
    	for (int j = 0; j < cols; j++) {
    	if (pv[i]->get(j)==0) {
    		Bitmap->Canvas->Pixels[i][j] = clWhite;
    	}
    else    Bitmap->Canvas->Pixels[i][j] = clBlack;
    	}
    }
    Bitmap->SaveToFile( "repgraph.bmp" );
    }
    

    Nun meckert der Compiler allerdings rum, er kenne den Qualifier 'Graphics' nicht. Wahrscheinlich muss ich noch irgendwas includen - aber was genau?


  • Administrator

    DocShoe schrieb:

    Wenn man das so pedantisch sieht hast du natürlich recht, aber bevor ich eine weitere Abhängigkeit in meine Projekte einführe benutze ich doch lieber das, was die Compilersuite von sich aus mitbringt.

    Wer sagt dir, dass er die VCL bereits verwendet? Nur weil man den Code Gear Kompiler verwendet, muss man doch nicht automatisch auch die VCL verwenden. Aber wenn er diese bereits verwendet, dann hast du natürlich schon recht, dass eine zusätzliche Abhängigkeit nicht unbedingt sinnvoll wäre. Kann TBitmap auch PNGs speichern oder sonst ein etwas besser komprimiertes Format als bmp?

    Grüssli



  • Stellt sich die Frage, ob die Komprimierung für ihn wichtig ist...

    Falls sie es nicht ist, hat er mit TBitmap eine sehr angenehme und leicht zu verwendende Klasse, die meines Wissens aber nur .bmp speichert.

    Falls seine Bilder sehr groß sind, ist er mit libpng wohl besser beraten.



  • Soweit ich weiss kann TBitmap nur das Bitmap Format schreiben, aber es gibt noch eine Klasse TJPEGImage, die (oh Wunder!) Grafiken im JPG Format speichert.

    @Daramos
    Du musst den Header <graphics.hpp> und <boost/smart_ptr.hpp> inkludieren.

    PS:
    Wenn du das ohne boost machen willst musst du dich selbst um das Zerstören der Bitmap kümmern:

    #include <vcl.h>
    #include <graphics.hpp>
    
    Graphics::Bitmap Bmp = new Graphics::TBitmap();
    
    // Code wie oben
    
    delete Bmp;
    


  • DocShoe schrieb:

    boost::shared_ptr<Graphics::TBitmap> Bitmap( new Graphics::TBitmap() );
    Bitmap->PixelFormat   = pf32bit;
    Bitmap->Width         = Width;
    Bitmap->Height        = Height;
    
    if( Bitmap->Canvas->Pixels[0][0] == clBlack )
    {
       Bitmap->Canvas->Pixels[0][0] = clWhite;
    }
    Bitmap->SaveToFile( "c:/bitmap.bmp" );
    

    Das ist wieder ein schönes Beispiel dafür, wie man shared_ptr nicht einsetzen sollte. Es gibt auch noch scoped_ptr , wenn kein geteilter Besitz nötig ist. Der ist hier viel sinnvoller. Selbst std::auto_ptr wäre noch geeigneter.



  • Nexus schrieb:

    Das ist wieder ein schönes Beispiel dafür, wie man shared_ptr nicht einsetzen sollte. Es gibt auch noch scoped_ptr , wenn kein geteilter Besitz nötig ist. Der ist hier viel sinnvoller. Selbst std::auto_ptr wäre noch geeigneter.

    Genau! Bis man sich irgendwann entschliesst (bzw. die Notwendigkeit eintritt), die Grafik doch irgendwie anzeigen zu wollen oder irgendwie anders weiter benutzt werden soll. Und baut dann von scoped_ptr/auto_ptr doch auf smart_ptr um. So ganz ohne Kontext kann man an fast jedem Code irgendwas aussetzen... weisst du, ob der vollständige Code nicht aus mehreren Funktionen besteht, von denen eine die Grafik erzeugt und eine andere die Grafik speichert? Und eine dritte vielleicht sogar die Grafik ausdruckt? Oder es mehrere Matrizen gibt, zu der jeweils eine Grafik in einer std::map abgelegt wird?
    Also manchmal glaube ich wirklich, dass hier nur gepostet wird, um irgendein Posting wegen einer Spitzfindigkeit anzuprangern...



  • Dieser Thread wurde von Moderator/in evilissimo aus dem Forum C++ in das Forum VCL (C++ Builder) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • DocShoe schrieb:

    Also manchmal glaube ich wirklich, dass hier nur gepostet wird, um irgendein Posting wegen einer Spitzfindigkeit anzuprangern...

    Nur nicht gleich so empfindlich reagieren.

    Ich wollte dich nur darauf hinweisen, dass shared_ptr oftmals nicht angebracht ist, auch wenn er "praktisch" zu sein scheint (im Sinne von, man muss nichts überlegen und bei möglichen Änderungen nichts umstellen). Für die Übergabe an weitere Funktionen braucht es keinen shared_ptr , da reichen Referenzen. Im Übrigen kann es gut sein, dass man mit scoped_ptr Fehler vermeidet, weil man den Zeiger nicht aus Versehen kopiert. Als klassischer RAII-Smartpointer ist er sicher zu bevorzugen.

    Wenn du dir dieser Thematik bewusst bist, okay. Aber es gibt eben einige Programmierer, die grundsätzlich einfach mal shared_ptr einsetzen, ohne dass sie ihn überhaupt wirklich brauchen. Ein weiteres Beispiel dafür sind Smart-Pointers in Containern, wenn Boosts Pointer-Container sich viel besser eignen würden.

    Und bevor sich Daramos so eine schlechte Technik noch abschaut, möchte ich das lieber erwähnen. Wie gesagt: Es war als konstruktive Kritik gedacht, nicht als Haarspalterei.



  • Nexus schrieb:

    Und bevor sich Daramos so eine schlechte Technik noch abschaut, möchte ich das lieber erwähnen.

    So eideutige Feindbilder möchte ich mal haben.

    Ein smart_ptr<> ist nicht "so eine schlechte Technik", sondern lediglich gegenüber einem Scoped-Pointer ein kleiner Overhead, der angesichts des Overheads der einhergehenden Allokation eines Bitmaps vollkommen irrelevant ist.

    Von allen Argumenten für Garbage Collection, die ich bisher gelesen habe, ist dieses Smart-Pointer-/Pointer-Container-/Move-Semantik-Chaos bei weitem das eindrücklichste 😃



  • audacia schrieb:

    Ein smart_ptr<> ist nicht "so eine schlechte Technik", sondern lediglich gegenüber einem Scoped-Pointer ein kleiner Overhead, der angesichts des Overheads der einhergehenden Allokation eines Bitmaps vollkommen irrelevant ist.

    Hier vielleicht. Aber wie soll man in zeitkritischen Anwendungen auf einmal plötzlich das Richtige auswählen, wenn man es vorher nie gemacht hat? Abgesehen davon halte ich es nicht für verkehrt, auch bei kleineren Dingen das richtige Sprach- oder Bibliotheksmittel zu wählen. "Schlechte Technik" sagte ich im Hinblick auf ein ständiges Verwenden von shared_ptr als GC-Ersatz (das meine ich im Allgemeinen, nicht auf DocShoe bezogen).

    audacia schrieb:

    Von allen Argumenten für Garbage Collection, die ich bisher gelesen habe, ist dieses Smart-Pointer-/Pointer-Container-/Move-Semantik-Chaos bei weitem das eindrücklichste 😃

    Ja, sich Besitzverhältnisse genau zu überlegen scheint auch für viele Leute eine ziemliche Herausforderung zu sein. Aber wenn man wenig denken will, nimmt man sowieso nicht C++.


Anmelden zum Antworten