AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Grafik optimieren TPaintBox
Thema durchsuchen
Ansicht
Themen-Optionen

Grafik optimieren TPaintBox

Ein Thema von TUX_der_Pinguin · begonnen am 14. Jul 2006 · letzter Beitrag vom 14. Jul 2006
Antwort Antwort
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
609 Beiträge
 
Delphi 11 Alexandria
 
#1

Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 12:30
Hallo,

ich lasse in einem Projekt eine Grafik anzeigen ( Koordinaten Systeme
mit Messpunkten ). Das ganze lasse ich auf einer TPaintBox zeichnen,
ansich klappt alles jedoch flackert die Grafik wenn diese neugezeichnet
wird und ist auch recht langsam wenn ich sehr viele Messpunkte in
mein Koordinatensystem einzeichne ( > 1.000 Messwerte ).

Ich zeichne alles on the fly, habe mir schon überlegt das ganze in ein
Bitmap zuzeichnen und nur noch das Bitmap anzuzeigen, habe das noch
nicht ausprobiert.

Jemand eine idee bzw. tipps wie man so etwas machen könnte ich mein generell, solch Grafikoperationen zubeschleunigen das das ganze nicht
mehr so träge angezeigt wird und nicht mehr flackert.

Vielen dank im voraus.

mfg


TUX

p.s. Das Projekt ist in Delphi 7 Personal Edition entwickelt worden.
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#2

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 12:32
Vermutlich verwendest du Application.ProcessMessages nach jedem Eintragen eines Punktes?
Wenn ja, dann lass dieses mal weg. Das Bild wird dann nicht mehr nach jedem Zeichnen aktualisiert, der Aufbau ist dafür aber erheblich schneller.

Florian
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
teebee

Registriert seit: 17. Jan 2003
Ort: Köln
460 Beiträge
 
Delphi 6 Professional
 
#3

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 12:50
Hier im Forum solltest Du einiges zum Thema Offscreen-Bitmaps finden.
Deine Anwendung wird dadurch nicht schneller, aber sie sollte nicht mehr flackern.

Gruß, teebee
  Mit Zitat antworten Zitat
TUX_der_Pinguin

Registriert seit: 1. Jun 2005
Ort: Anholt (NRW)
609 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 14:46
Naja so wirklich richtig flackern tut das Programm gar nicht, weil der
so langsam beim Zeichnen ist das man ihm zuschauen kann wie der nach und
nach die einzelnen Bereiche zeichnet, es sind einfach viele Zeichen
Operationen die das Programm macht, auf einem schnelleren Rechner,
ist mehr ein leichtes Flackern zusehen .. es ging mir halt darum mal andere Ansätze zu hören wie man etwas Zeichnet mit einigen 1.000 Zeichen Operationen Pro Grafik.

Ich habe mein Programm dahin gehend schon etwas optimiert die Grafik
nur so oft neu zumalen wie nötig aber wie bereits gesagt das zeichnen
ansich ist zu lahm.

mfg

TUX
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 15:04
Offscreen Bitmap wurde schon gesagt und ist deine Lösung. Bitmaps sind sehr wohl schneller zu zeichnen als direkt auf den Bildschirm.

Eine weitere Optimierung ist es ausgehend von dieser Offscreen Bitmap nur diejenigen rechteckigen Bereiche auf den Bildschirm zu kopieren die auch tatsächlich verändert wurden. Nehmen wir mal an das deine Meßpunkte grafisch örtlich in Gruppen auftreten, also ungleichmäßig auf dem Zeichenbereich verteilt sind. Dann ist es sinnvoll die Bitmap in NxM große Teilbereiche zu zerlegen und diese Teilbereich nach Veränderungen auf den Bildschirm zu kopieren. Diese Technik habe ich bei meinem Game Of Live Spiel so angewendet, weil auch dort ab einem bestimmten Spielfortschritt sich nur wenige Bildschirmbereiche tatsächlich verändern. Den Source solltest du hier in der DP finden können. Man verhindert damit effektiv das man über das komplette Neuzeichnen der Bitmap tatsächlich zb. nur 10% wirkliche Veränderungen und 90% unveränderte Bereiche neu gezeichnet werden.

Ein weiterer Vorteil, wenn man das alles schon hat, ist es nun das diese Bereiche einzelnen Threads zugeordnet werden. Dh. mehrere Thread arbeiten parallel und sind immer für Teilbereiche der Grafik zuständig. Sie zeichnen ihre Änderungen in separate Bitmaps und der Mainthread baut aus diesen Einzelnbitmaps quasi das Bildschirm Bild auf.

Und noch eine Möglichkeit besteht darin das eigentliche Kopieren der Teilbereiche der Offscreen Bitmap asynchron zu deren Veränderungen zu machen. Dh. man verändert zb. die Teilbereiche der Bitmap ca. 1000 mal in der Sekunde, zeichnet diese veränderten Teilbereich aber nur alle 20 Milliesekunden tatsächlich neu auf den Bildschirm. Das geht weil bei 20ms Aktualisierung schluß ist für unsere Augen, wir können nicht schneller sehen als 50 Frames pro Sekunde. Normalerweise reichen aber auch 2-4 Aktualisierungen des Bildschirmes pro Sekunde aus. Du sparst damit also die Prozessorzeit für Funktionen wie Invalidate und alles was normalerweise eben 1000 mal pro Sekunde nötigt wäre aber eigentlich sinnlos ist.

Man optimiert quasi Stück für Stück sein Program und der konzeptionelle Ansatz den du wählst entscheidet ob obige Optimierungen später möglich/einbaubar sind.

Eine weitere Möglichkeit ist es ein TPanel (Windowshandle erforderlich) hinter die TPainBox zu legen (TPaintBox ist alClient im TPanel). Nun fängt man die Windowsbotschaft wm_EraseBkGnd vom TPanel ab und tut darin einfach nichts wm_EraseBkGnd löscht den Bildschirmbereich dieses TPanels -> ergo TPainBox, jedesmal wenn man Invalidate aufgerufen hat. Das führt dann zum besagten Flackern. Im OnPaint() muß man bei jedem auftreffenden wm_EraseBkGnd dann ntürlich die Offscreen Bitmap komplett neu zeichnen oder zumindestens in den Bereichen die mit GetClipRgn(Canvas.Handle) als neu zu zeichnen enthalten sind. Das kannst du mit IsRectVisible(Canvas.Handle, TRect) überprüfen wenn du mit der Teilbereichs-Logik arbeiten möchtest.
Über wm_EraseBkGnd kannst du also schonmal aktiv das Flackern beseitigen, vorrausgesetzt du rufst im OnPaint() der TPainbox nicht als erstes FillRect(ClientRect) oder sowas auf.

Gruß Hagen
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 15:17
Noch ein Nachtrag dazu: Du kannst in der Paint Methode von der Paintbox auch mit IntersectRect() zum einen überprüfen ob du was zeichnen müsstest und zum anderen erhälst du bei einer Positiven Antwort sogar gleich das Rechteck des zu zeichnenden Teilbereiches. Dieses Verfahren wende ich (ist das von negaH beschriebene) in meinem Programm an und es ist recht effektiv. Und TCanvas bietet mit der Eigenschaft ClipRect schon das Rechteck, welches gezeichnet werden müsste.

Delphi-Quellcode:
Procedure TForm1.PaintBox1Paint(Sender: TObject);
Var
  lDrawRect: TRect;
Begin
  If IntersectRect(lDrawRect, PaintBox1.ClientRect, Canvas.ClipRect) Then
  Begin
    BitBlt(p_Canvas.Handle,
             lDrawRect.Left,
             lDrawRect.Top,
             lDrawRect.Right - lDrawRect.Left,
             lDrawRect.Bottom - lDrawRect.Top,
           DeinBitmap.Canvas.Handle,
             lDrawRect.Left - PaintBox1.ClientRect.Left,
             lDrawRect.Top - PaintBox1.ClientRect.Top,
           SRCCOPY);
  End;
End;
DeinBitmap ist dein Bitmap mit der Grafik als gesamtes (die Off-Screen-Bitmap)
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#7

Re: Grafik optimieren TPaintBox

  Alt 14. Jul 2006, 15:24
Eine feinere Auflösung als mit Canvas.ClipRect erreichst du mit GetClipRgn() oder IsRectVisible(). Windows verwaltet komplexere Zeichenbereiche in sogenannten Region's -> Regionen. Das sind komplexe Datenstrukturen die nicht nur einfache Rechtecke darstellen können sondern ganze Ansammlungen von Rechtecken.

Entweder holt man sich mit GetClipRgn() zu einem Canvas.Handle -> Geräte Kontext -> Device Context -> DC -> hDC diese Region und kann dann über eigene Regions mit zb. der Funktion CombineRgn() alle Boolschen Operationen durchführen, also auch IsRectViusible() simmulieren, oder aber man benutzt IsRectVisible(). Möchte man zb. den Bereich der neugezeichnet werden soll schon im vorhinein clippen/beschneiden und dann ausfüllen dann kann man auch mit FillRgn() statt mit FillRect() arbeiten. FillRect() würde intern die Region holen und dann den übergebenen TRect in eine Region umwandeln und eine Intersection erzeugen. Mit dieser Intersection-Region (CombineRgn(RGN_AND) ) wird dann FillRgn() aufgerufen. So gesehen kann man das autom. machen lassen mit einem Aufruf von FillRect() oder eben selber manuell durchführen über GetClipRgn(), CombineRgn() und FillRgn(). Vorteil der letzteren Methode ist es das man wesentlich mehr EInfluß nehmen kann, zb. noch eigene Bereich zergliedern etc.pp.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz