PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeichenroutine dauert zu lange



avrrobot
07.03.2012, 20:24
Hallo,

Nachdem ich nun auch ein bisschen mit Computerprogrammen arbeite, habe ich folgende Frage:
Ich habe in Programm, welches mittels zwei for() schleifen in der Zeichenroutine eine Art Bild zeichnet.
Jetzt ist bloß das Problem, das diese Schleifen relativ viel Leistung brauche, Zeit weiß ich aber nicht so genau.
Ich habe allerdings bereits herausgefunden, das es nicht die Schleifen sind, sondern das zeichnen. (-> also Rectangle())
Das wundert mich allerdings etwas, da eine so einfache Aufgabe eigentlich nicht so lange dauern dürfte.
Ach ja, ich programmiere C++, direkt mit winapi. Ich verwende allerdings Doppelbuffering, aber ich glaube nicht,
das es daran liegt. Falls natürlich jemand eine Möglichkeit kennt, ein Bitmap direkt zu zeichnen,
bei der lediglich die Flächen gezeichnet werden, die nicht weiß sind, und bei der nicht die Pixel mit einem logischen Operator
mit dem Hintergrund verknüpft wird, dann wäre das natürlich noch besser. Mit BitBlt oder StetchBlt kann man das eben soweit ich weiß nicht.
Kann mir da irgendjemand weiterhelfen?

MfG avrrobot

robocat
07.03.2012, 20:39
So ungern du das vielleicht hören magst, am schnellsten sollte sich mit DirectDraw zeichnen lassen, was natürlich ein bisschen Aufwand mit sich bringt. Die WinAPI Zeichenfunktionen sind wirklich nur begrenzt verwendbar. http://katze.dead-men.de/index.php?content=67
Wenn es dir genügt, ein Bitmap selbst zu zeichnen, dann kannst du natürlich Speicher reservieren, dort deine Bits setzen, und das dann darstellen lassen. Besonders schnell wird das aber vermutlich nicht. Ich könnte Code dafür irgendwo rumliegen haben.

Grüße von der Katze

Slein
07.03.2012, 20:40
Mahlzeit!

Evtl. wird das Fenster nach jeder Zeichenoperation upgedatet.
Komplexere Sachen am Besten erst in ein Bitmap im Speicher zeichnen,
wenns dann fertig ist rüber ins Fenster kopieren (dann natürlich nicht
pixelweise in Schleifen...).

Schwer zu sagen ohne Code und ohne zu wissen was du genau mit
Doppelbuffering meinst ;)

ePyx
07.03.2012, 20:43
Wenn du mit der WinAPI arbeitest, solltes du nicht direkt auf die Ausgabe zeichnen, sondern in eine Bitmap. Anschließend via BitBlt die BitMap direkt auf den Zeichenkontext der Anzeige kopieren. Das geht um Einiges schneller. Des Weiteren sollte die Daten möglichs in einem Thread erstellt werden, damit die GUI zeichnen kann. Sonst blockieren die sich gegenseitig.

Über die Apllikations-Instanz könnte man auch einen Speicherbereich deklarieren, auf den beide Elemente zugreifen. Dabei aber nicht vergessen, das der Zugriff konkurrierend statt findet. Sprich an die Gegenmaßnahmen denken.

avrrobot
07.03.2012, 20:43
Ja, das meine ich, das funktioniert auch ganz gut.
Ich hab das auch schon mal mit nem Bitmap gemacht, aber das war nicht so ganz das was ich brauche.
Edit: Da war ja noch jemand schneller :), was meinst du genau mit den Daten im Thread?

ePyx
07.03.2012, 20:49
Na wo baust du die Zeichnung zusammen ? Im GUI-Thread ( Hauptprogramm) oder seperat ? Wird die Anzeige stetig aktualisiert? oder ist sie statisch ? Wenn statisch, wird dann jedes mal durch eine Paint-Message die Zeichenroutine aufgerufen ?

avrrobot
07.03.2012, 20:51
Im Prinzip zeichne ich direkt in der Paint Message, ich lasse sie durch windows aufrufen,
blockiere sie aber, wenn die Zeit zum letzten mal zeichnen zu gering ist.

ePyx
07.03.2012, 20:52
Das heisst du baust die dann aber neu auf ? Verändert sich denn der Inhalt der Zeichnung, oder willst du nur sicherstellen, dass eine Größenänderung des Rahmens eine erneute Skalierung verursacht ?

avrrobot
08.03.2012, 05:48
Ja, jedes mal, wenn ich zeichne, sieht das ganze etwas anders aus, es verändert sich schon etwas.
Und ja, ich bau das ganze jedesmal neu auf.

avrrobot
08.03.2012, 18:56
Oder gibt es vielleicht eine Möglichkeit, direkt auf das zum Fenster kompatible Bitmap
im RAM zu zeichnen? Die Zeichenroutinen dauern ja vielleicht lange, aber es muss doch schnell gehen, auf ein Byte aus dem
Bitmap im RAM zuzugreifen. Weiß jemand vielleicht, ob das geht, oder wie man einen Pointer auf das Bitmap herbekommt?

ePyx
08.03.2012, 19:16
Zitiere mich selbst ungern, aber :


Wenn du mit der WinAPI arbeitest, solltes du nicht direkt auf die Ausgabe zeichnen, sondern in eine Bitmap. Anschließend via BitBlt die BitMap direkt auf den Zeichenkontext der Anzeige kopieren.

Mal einfach in deinem Programm eine Bitmap und die stellst du beim Eintreffen der WM_PAINT-Message dar. Das wird, auch wenn du die Bitmap nicht in einem anderen Thread aktualisierst, wesentlich schneller gehen, als dein jetziger Ansatz.

avrrobot
08.03.2012, 19:18
Ja, auch das mache ich bereits, das funktioniert auch ganz gut, obwohl ich das eigentlich gemacht hatte,
damit das ganze nicht mehr flackert.
Aber wenn ich zum Beispiel 250000 Punkte zeichne, dann dauert das fast eine Sekunde, das muss doch irgendwie schneller gehen.

ePyx
08.03.2012, 19:33
Naja wie gesagt, dass ganze sollte ausgelagert werden. Dein Programm erzeugt ja einen Hauptthread, also dein Hauptprogramm. Dieser kann Daten nur sequentiell abarbeiten. Also wird er entweder auf das Ausgabegerät Zeichnen ( also Bitmap auf Gerätekontext) oder die Daten in deine Bitmap zeichnen. Aber er wird nie beides machen.

Deshalb werden solche Sachen immer in separate Threads ausgelagert. Die Teilen sich in C einen Zeiger auf die Daten, der Worker-Thread ( der die Daten verarbeitet und deine Bitmap aktualisiert), muss dem Thread der grafischen Oberfläche ( GUI ) signalisieren, dass neue Daten da sind und die Bitmap fertig ist. Letzteres ist nötig, damit nicht beide auf die Daten zugreifen und es zu keiner Speicherzugriffsverletzung kommt (Stichwort Mutex oder Semaphore).

Dann brauchst du sozusagen nur das "Ich habe fertig"-Flag beim Eintreffen der WM_PAINT-Message abfragen und die Bitmap nur dann neuzeichnen. Ein weiterer aber aufwendigerer Weg ist nur die Punkte deiner Bitmap zu aktualisieren, die sich auch wirklich geändert haben.