In Bitmap speichern...



  • Das wär echt Klasse, vielen Dank schon mal im vorraus!!! Macht nix wenn es etwas länger geht, arbeite eh erst morgen dran weiter!
    Viele Grüße
    Christian



  • So nun ist das Projekt fertig, aber dummerweise hab ich meine URL-PWD nicht mit in der Stadt wo ich gerade arbeite. Ich hab ein MFC-SDI Projekt erzeugt und nur die OnPaint gefüllt, bei mir wird sauber eine Bitmap erzeugt. Den Quellcode der WriteBitmap habe ich nicht verändert.

    Also vielleicht hilft die auch der Code der OnPaint:

    void CChildView::OnPaint() 
    {
      CPaintDC dc(this); // Gerätekontext zum Zeichnen
    
      //na dann, malen wir mal irgendwas was ins HDC
      dc.Rectangle(rand()%50,rand()%50,600, 600);
      RECT r;
      CBrush brush;
      r.left=rand()%50;
      r.top=rand()%50;
      r.bottom=rand()%800;
      r.right=rand()%800;
      brush.CreateSolidBrush(RGB(255,255,0));
      //ein gelbes Rechteck
      dc.FillRect(&r, &brush);
      //auch noch einen Text
      dc.TextOut(100,100,"Das ist ein Text in einer Bitmap!");
    
      //jetzt das ganze als Bitmap abspeichern
      CBitmap bmp; //Bitmap-Objekt
      CDC memdc;	//Speicherkontext
      RECT cr;	//für die Grösse des Clients
    
      memdc.CreateCompatibleDC((CDC*)&dc);
      GetClientRect(&cr); //Ausdehnung des Clientsbereichs ermitteln
      //passende Bitmap in der Grösse des Clients anlegen
      bmp.CreateCompatibleBitmap((CDC*)&dc, cr.right,cr.bottom); 
    
      //Speicherkontext mit der Bitmap verbinden
      memdc.SelectObject(bmp);
      //In den Speicherkontext (eigentlich in die Bitmap!) den Inhalt des dc kopieren
      memdc.BitBlt(0,0,cr.right,cr.bottom,(CDC*)&dc,0,0,SRCCOPY);
    
      //Jetzt die Bitmap speichern
      WriteBitmap("c:\\testbitmap.bmp",bmp.operator HBITMAP(), memdc.m_hDC);
    
      // Rufen Sie nicht CWnd::OnPaint() für Nachrichten zum Zeichnen auf
    }
    

    Bei mir funktioniert das wie es soll. Wenn man das Fenster scaliert, wird immer
    eine neue Zeichnung erstellt und in die Bitmap-Datei geschrieben.
    Sollte für ne Demo auch reichen...

    Schreib wieder bei Fragen.
    Gruss René



  • Vielen Dank, werd es gleich morgen ausprobieren, sobald ich auf arbeit bin!
    Werd dann das Ergebnis hier posten!

    Schönen Abend noch und viele Grüße
    Christian



  • Jetzt habe ich mal kurz eine dialogf. Anwendung erstellt mit einem Button "Speichern" in OnClicked() habe ich den Code kopiert. Jetzt wird zwar ein Bitmap erstellt aber in diesem ist ein Screenshot von meinem Dialog!! Liegt das daran dass ich es nicht in OnPaint() oder wie kann denn das kommen??



  • Also gut, dann bis morgen und auch schönen Feierabend!

    Gruss René



  • Guten morgen 🙂
    Das funktioniert jetzt alles echt wunderbar, nur ein Problem besteht noch: Er zeichnte mir das was er in die Datei zeichnet auch auf den Bildschirm!! Dadurch überschreibt er mir meine Grafik! Erst wenn ich das Fenster minimiere und wieder maximiere ist wieder alles beim alten! Hast du dafür eine Lösungsidee??



  • Das Problem stellt sich doch noch etwas anderst dar, er macht folgendes: Er zeichnet erst auf den Bildschirm, macht dann vom ganzen Bildschirm einen Screenshot und speichert das in der Datei. Wenn ich nämlich den Bereich größer mache sehe ich sogar die Taskleiste im Bitmap! 😮
    Ich verzweifle 😞 😞 🙄 🙄



  • Du musst halt meine Zeichenfunktionen rausnehmen und Du solltest auch GetCLientRect aufrufen um die Grösse deines Zeichenfensters zu ermitteln.
    Ich hab in dem Beispiel die Bitmap genau in dessen Grösse erstellt. Machst
    Du die Bitmap grösser bekommst du auch Pixel ausserhalb Deines Fensters in die Bitmap gelegt 😉

    gruss



  • Ja, das hab ich schon gemacht, aber das Problem ist halt dass in die Bitmap etwas anderes soll als das was auf dem Bildschirm ist, deshalb muß sie ja auch größer sein! Das in der bitmap soll total unabhängig von dem aufm Bildschirm sein!



  • Also ich konnte Dir nur soweit helfen das Du eine Bitmap erzeugen kannst.
    Um jetzt nun genau zu wissen WAS in die Bitmap rein soll, muss ich halt auch mal
    in den Code sehen können. Da das nicht geht, brauche ich dann eben ganz detailierte Informationen
    darüber. Sonst wird das ganz schwer und ist nur ein rumgerate und probieren...

    😉

    gruss



  • Okay, also ich versuch das mal zu erklären:
    Ich habe neben vielen, vielen anderen Funktionen, die alle etwas auf den Bildschirm zeichnen diese Funktion:

    //Zeichnet das Koordinatensystem
    CZeichnen::ZeichneKoordinatensys(CDC *pDC)
    {
    double druckenVerschieb=0;
    if(m_druckenFaktor.x!=1)
       druckenVerschieb=m_druckenMitte.x;
    
       //Y-Achse mit Pfeil
    pDC->MoveTo(80*m_druckenFaktor.x,605*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(80*m_druckenFaktor.x,100*m_druckenFaktor.y+druckenVerschieb);
    pDC->MoveTo(80*m_druckenFaktor.x,100*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(75*m_druckenFaktor.x,107*m_druckenFaktor.y+druckenVerschieb);
    pDC->MoveTo(80*m_druckenFaktor.x,100*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(85*m_druckenFaktor.x,107*m_druckenFaktor.y+druckenVerschieb);
    
      //X-Achse mit Pfeil
    pDC->MoveTo(75*m_druckenFaktor.x,600*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(700*m_druckenFaktor.x,600*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(693*m_druckenFaktor.x,595*m_druckenFaktor.y+druckenVerschieb);
    pDC->MoveTo(700*m_druckenFaktor.x,600*m_druckenFaktor.y+druckenVerschieb);
    pDC->LineTo(693*m_druckenFaktor.x,605*m_druckenFaktor.y+druckenVerschieb);
    

    So, wenn der Anwender jetzt auf den "Speichern" Button klickt, dann soll diese, und NUR diese Funktion in ein Bitmap mit weißem Hintergrund gezeichnet und gepseichert werden.
    Ich habe jetzt folgendes probiert:

    void CZeichnen::OnSave() 
    {	
    static char BASED_CODE szFilter[]="Bitmap-Dateien (*.bmp)|*.bmp||";
    CString filename;
    CFileDialog saveFile(FALSE, ".bmp", filename, OFN_HIDEREADONLY,szFilter);
    
      if(saveFile.DoModal()==IDOK)
      {
    	CDC *cdc; 
    	cdc=GetDC();
    	cdc->Rectangle(0,0,900, 1000); 
    
    	ZeichneKoordinatensys(cdc);
    
    	//jetzt das ganze als Bitmap abspeichern 
    	CBitmap bmp; //Bitmap-Objekt 
    	CDC memdc;    //Speicherkontext 
    	RECT cr;    //für die Grösse des Clients 
    
    	cr.right=900;
    	cr.bottom=1000;
    	//memdc.CreateCompatibleDC((CDC*)&cdc); 
    	memdc.CreateCompatibleDC(NULL); 
    
    	//GetClientRect(&cr); //Ausdehnung des Clientsbereichs ermitteln 
    	//passende Bitmap in der Grösse des Clients anlegen 
    	bmp.CreateCompatibleBitmap((CDC*)cdc, cr.right,cr.bottom);  
    
    	//Speicherkontext mit der Bitmap verbinden 
    	memdc.SelectObject(bmp); 
    	memdc.BitBlt(0,0,cr.right,cr.bottom,(CDC*)cdc,0,0,SRCCOPY); 
    
    	//Jetzt die Bitmap speichern 
    	filename=saveFile.GetPathName();
    	WriteBitmap(filename,bmp.operator HBITMAP(), memdc.m_hDC); 
       }
    
    }
    

    Das funktioniert jetzt ja auch alles soweit, nur das Problem ist jetzt eben, dass unter das Koordinatensystem auch noch Text soll, aber da ist die Taskleiste in meinem Bitmap zu sehen und darunter nur noch schwarz! Dort soll aber einfach nur ein weißer Bereich sein, in den ich noch mehr zeichnen bzw. schreiben kann.
    Ich hoff die ganze Erklärung ist einigermaßen verständlich geschrieben. 🙄 😕



  • sag mal darf ich deinen Namen als Destruktoraufruf ansehen



  • Ne, nur Christian war einfach schon belegt, und in nem anderen C++ Forum werden bei unregistrierten immer das ~ vorangestellt, also hab ich das hier auch gemacht...
    Gruß Christian



  • Nur mal ne schnelle Lösung, für genaueres muss ich nacher nochmal den Code durchgehen.

    Das Problem ist derzeit, das die Bitmap zwar gross genug ist, aber nur der der
    Teil des DC reinkopiert wird, wie eben das Fenster gross ist. Die Lösung sollte
    sein die Bitmap VOR deinen eigentlichen Zeichenfunktionen erstmal komplett Weiss zu füllen
    (damit ist dann auch die Taskleiste ect. weg) und dann die Zeichenoperationen auf die Bitmap
    auszuführen. Dazu solltest Du in der CZeichnen::ZeichneKoordinatensys(CDC *pDC);
    zuerst ein pDC->FillRect()
    aufrufen und dabei die Koordinaten left=0,top=0,right=900,bottom=1000 im zu übergebenen LPRECT eintragen.

    Mal sehen ob das schon reicht, sonst später was anderes.
    gruss René

    PS: Leider muss ich nebenbei ein wenig arbeiten, kann also ein wenig dauern 😉



  • Hat leider auch net funktioniert, da die ZeichneKoordinatensys() ja auch noch zum zeichnen auf den Bildschirm und zum drucken verwendet wird kann ich dort drin ja nicht direkt in ein Bitmap sondern immer nur in den CDC zeichnen.



  • Wenn der Code doch nur nicht so geheim wäre, ich bin im Moment etwas ratlos...

    Schreib mich doch mal im ICQ an, damit das hier nicht in einem Chat ausartet.
    #89063833

    gruss René



  • ICQ geht leider net, ist bei uns im Geschäft net erlaubt 😞 Selbst mim INet ist das so ne Sache..
    Es kann doch aber eigentlich net am Code liegen, Ich hab doch einfach nur ein paar Funktionen, denen ich entweder den Bildschirm oder den Drucker CDC übergeb und die mir dann etwas auf den Bildschirm bzw. Drucker malen und schreiben. Jetzt muß es doch möglich sein, eine Art "neutralen" CDC zu erzeugen, dort hinein zu malen, schreiben usw., wohin und was ich will und diesen dann in ein leere, weißes Bitmap zu kopieren. Das Problem bis jetzt ist einfach dass er auf den Bildschirm zeichnet und dann das was auf dem Schirm ist in das Bitmap zeichnet. Ich bin echt ratlos. Hat das denn echt noch niemand gemacht, das ist doch eigentlich ein ziemlich alltägliches Problem, oder etwa nicht???! Wenn ich in Paint etwas male kann ich es ja auch in ner bmp speichern, also muß es doch möglich sein!!



  • Hier nun eine Methode, die von irgendwo beliebig aufgerufen werden kann.
    Sie erzeugt eine 1000x9000x24 grosse Bitmap, füllt den Hintergrund weiss auf
    und zeichnet dann einiges in das Bild. Das ganze passiert unsichtbar im
    Hintergrund, so wolltest es ja haben. Also was die Funktion malt, ist nicht
    das was im Fenster zu sehen ist. Deine Funktion musst jetzt nur noch anpassen,
    dann ist der Rest geschichte... (hoffe ich mal)

    Code ist weitgehend kommentiert.

    void CChildView::OnMaleIrgendwasInEineBitmapUndSpeichereSieAb() //geiler Name?
    {
      CDC *dc=new CDC; //ein neuer unabhängiger DC
      CBitmap *membmp=new CBitmap; //eine Bitmap die den DC representiert
    
      membmp->CreateCompatibleBitmap(GetDC(),1000,900); //Speicher-Bitmap erzeugen
      dc->CreateCompatibleDC(GetDC()); //Speicher-DC initialisieren
      dc->SelectObject(membmp); //mit Bitmap verknüpfen, gezeichnet wird alles in die BMP!
    
      //na dann, malen wir mal irgendwas was in die Bitmap
      RECT r;
      CBrush *brush=new CBrush;
    
      //Hintergrund: zuerst die BMP komplett weiss füllen 
      brush->CreateSolidBrush(0x00FFFFFF);
      r.left   = r.top = 0;
      r.right  = 1000;  //1000 breit
      r.bottom = 900;   //900 hoch
      dc->FillRect(&r, brush);
    
      //jetzt irgendwas reinmalen, ich weis kein Kunststück...
      dc->Rectangle(rand()%50,rand()%50,600, 600);
      r.left=rand()%50;
      r.top=rand()%50;
      r.bottom=rand()%800;
      r.right=rand()%800;
      brush->DeleteObject();
      brush->CreateSolidBrush(RGB(255,255,0));
      //ein gelbes Rechteck
      dc->FillRect(&r, brush);
      //auch noch einen Text
      dc->TextOut(100,100,"Das ist ein Text in einer Bitmap!");
    
      //jetzt das ganze als Bitmap abspeichern
      WriteBitmap("c:\\testbitmap.bmp",membmp->operator HBITMAP(), dc->m_hDC);
    
      //Aufräumen und Speicher freigeben
      dc->DeleteDC();
      delete dc;
      brush->DeleteObject();
      delete brush;
      membmp->DeleteObject();
      delete membmp;
    }
    

    Nun sollte das langsam mal Funktionieren, gell? 🙄
    Gruss René



  • Guten Morgen,
    es funktoniert SUPER!!! Riesen großes Dankeschön!!! Echt Klasse!!

    Viele Grüße und einen schönen Freitag 🙂
    Christian



  • Guten Morgen,

    dann bin ich ja beruhigt. Schönes Wochenende und viel Erfolg beim Programmieren.

    Gruss René


Anmelden zum Antworten