Autor Beitrag
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mo 11.11.02 02:31 
Ich fange mal mit einem Beispiel an. Nehmen wir an, daß ich zwei Bitmaps habe die 100 Pixels breit und hoch sind. Beide haben also die gleiche Maße. Nun will ich das rechte untere Viertel der einen Bitmap in das linke obere Viertel kopieren. Das könnte ich z.B. so machen:
ausblenden Quelltext
1:
Bmp1.Canvas.Draw(-50, -50, Bmp2);					

Sieht einfach aus. Die andere Variante könnte so aussehen:
ausblenden Quelltext
1:
Bmp1.Canvas.CopyRect(Rect(0, 0, 50, 50), Bmp2.Canvas, Rect(50, 50, 100, 100));					

Natürlich könnte man auch BitBlt anwenden, aber darum geht es nicht.

Die erste Variante ist einfach. Alles was zuviel ist wird von dem System abgeschnitten, der Rest landet in der Bitmap. Die zweite Variante ist schwieriger, da ich die Bereiche selbst vorher berechnen muß. Bei beiden Varianten sind die Ergebnisse aber die gleich.

Nun könnte man sich fragen wieso das ganze. Klar, bei einer kleinen Grafik ist das nichts. Da gibt es wahrscheinlich kein Geschwindigkeitsvorteil. Problematisch wird es aber wenn es hunderte Bitmaps in der Sekunde sind und sie auch etwas größer als 100 Pixel sind.

Meine Frage ist jetzt die: weiss einer wie das bei Canvas.Draw funktioniert? Kopiert Draw Pixel für Pixel die Bitmap und prüft ob der Pixel außerhalb des Bereichs ist? Das macht sie dann eventuell einige tausend mal. Oder berechnet sie vorher eine Region und kopiert nur diese Region rüber?

Noch ein Beispiel um es zu verdeutlichen. Ich hab eine Bitmap (Bmp1) die 10x10 Pixel ist und eine (Bmp2) die 2000x2000 Pixel ist. Nun kopiere ich die Große in die kleine:
ausblenden Quelltext
1:
Bmp1.Canvas.Draw(5, 5, Bmp2);					

Nun kann man sehen, daß ca. 99% des großen Bildes außerhalb sind. Warum also nicht vorher die wichtige Region berechnen und nur diesen Bereich kopieren. Natürlich kann ich mir das sparen wenn Draw das bereits macht. Kann aber auch sein, daß Draw eben Pixel für Pixel kopiert und alles drüber nur ignoriert. Zwar glaube ich das nicht, aber ich frag mal lieber. Leider hab ich die Pas Version der Unit nicht. Würde aber auch nichts bringen, da Draw wahrscheinlich auf BitBlt zugreift und BitBlt die ganze Arbeit erledigt. An der Frage ändert sich aber nichts. Dann eben BitBlt. Kopiert BitBlt Pixel für Pixel und ignoriert die die außerhalb sind oder wird vorher ein Bereich berechent?
OregonGhost
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 215



BeitragVerfasst: Mo 11.11.02 13:21 
Bei BitBlt muss man die Quell- und Zielkoordinaten sowie die Breite und Höhe des zu kopierenden Bereichs angeben. Falls TCanvas.Draw also BitBlt verwendet, muss es diesen Bereich berechnen. Da Bitmaps immer rechteckig sind wäre etwas anderes auch nicht sinnvoll.

Warum probierst du es nicht einfach aus, zum Beispiel mit deiner besagten 5x5 Bitmap und da kopierste eine 4096x4096x32 (=64MB) Bitmap rein? Dann kopierst du eine weitere 5x5 Bitmap in die erste, und wenn das deutlich schneller war, dann ist TCanvas.Draw wohl doch nicht so intelligent :roll:

Oh, kleiner Nachtrag:
Microsoft hat folgendes geschrieben:

BitBlt only does clipping on the destination DC.

Heißt, das Rechteck wird wohl automatisch beschnitten ;c)

_________________
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mo 11.11.02 17:39 
OregonGhost hat folgendes geschrieben:
Nachtrag:
Microsoft hat folgendes geschrieben:

BitBlt only does clipping on the destination DC.

Heißt, das Rechteck wird wohl automatisch beschnitten ;c)


Das es automatisch beschnitten wird ist klar, nur auf welche Art.

Ich hab einige Tests durchgeführt und festgestellt, daß man eine 20x20 und 2000x2000 in eine 10x10 Bitmap kopieren fast genauso schnell ist. Genau kann ich das aber nicht weder mit Timer, noch über GetTickCount eine vernünftige Zeit bekomme (obwohl ich das ganze in einer 1000'er Schleife hatte).

Mir geht darum auch die letzte Möglichkeit eines Geschwindigkeitsvorteils auszunutzen. Ich glaube aber, daß niemand mir diese Frage genau beantworten wird (bis auf MS).

Vieleicht schreib ich so eine Funktion und mache nochmal neue Tests.
AndyB
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1173
Erhaltene Danke: 14


RAD Studio XE2
BeitragVerfasst: Mo 11.11.02 17:48 
Alle API Grafikfunktionen zeichnen nur das, was nötig ist, da alle Parameter durch ein automatisches Clipping laufen. Weil selbst Regions in eine Ansammlung von Rechtecken zerlegt werden, geht das Clipping recht schnell von statten. Ist nur 1 Rechteck als Clip-Bereich vorhanden (Jede Komponente ist ja ein Rechteck, auch wenn nicht immer ersichtlich), geht das ganze mit sehr wenig Rechenzeit von statten. Wenn du nun bei BitBlt noch selbst Berechnungen anstellst, dann wird das ganze doppelt durchgeführt.

_________________
Ist Zeit wirklich Geld?
Popov
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mo 11.11.02 18:01 
Das hab ich mir auch gedacht und deshalb gefragt. Bei den Tests hat es nichts gebracht den Reckt Bereich vorher anzugeben. Wobei nichts kann ich nicht sagen, da ich das ganze bis jetzt nicht 100% messen konnte.

War eben eine Frage die mich beschäftigt hat.

Ich werde einfach davon ausgehen, daß Windows das diese Arbeit für mich erledigt.
OregonGhost
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 215



BeitragVerfasst: Mo 11.11.02 20:22 
Zitat:
Ich werde einfach davon ausgehen, daß Windows das diese Arbeit für mich erledigt.
Das solltest du auch, wenn man den Preis für eine Windows-Lizenz bedenkt ;c)

Für genaue Messungen kannst du übrigens QueryPerformanceCounter() verwenden, und du musst als kleine ja auch nicht 10x10 oder so nehmen, sondern meinetwegen 2048*2048 und als große 8192*8192 zum Beispiel...

_________________
Oregon Ghost
---
Wenn NULL besonders groß ist, ist es fast schon wie ein bisschen eins.
Ist die Frage beantwortet? Das Problem gelöst?

Dann klicke hier, um das Thema entsprechend zu markieren!