AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Transparentes Bitmap verschieben

Ein Thema von runner · begonnen am 29. Jan 2014 · letzter Beitrag vom 30. Jan 2014
Antwort Antwort
runner

Registriert seit: 13. Jan 2006
36 Beiträge
 
#1

Transparentes Bitmap verschieben

  Alt 29. Jan 2014, 19:43
Hallo zussamen,

ich zeichne mit transparentblt ein Bitmap auf eine Canvas und möchte anschließend das Bitmap verschieben. Wie mache ich das am besten ohne das der Hintergrund ständig neu gezeichnet werden muss?


Gruß Peter
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#2

AW: Transparentes Bitmap verschieben

  Alt 29. Jan 2014, 20:11
Vermutlich gibt es eine ganz elegante Lösung, die einzig mir bekannte ist die mit zwei Bitmaps.

Ich gehe hier davon aus, dass du nur eine Bitmap hast. Mit mehreren wird es etwas komplexer.

Das Bild für deinen Hintergrund kopierst du zusätzlich in eine Hintergrund-Bitmap. Wenn du nun deine transparente Bitmap verschieben möchtest, kopierst du zuerst die alte Position in eine TRect Variable. Nun, da du den Hintergrund in der Hintergrund-Bitmap gespeichert hast, kopierst du diesen "sauberen" Bereich aus deiner Hintergrund-Bitmap auf deine Leinwand. Dann zeichnest du deine transparente Bitmap an die neue Stelle der Leinwand.

Du hast mit der Methode nicht den ganzen Hintergrund ausgetauscht, sondern nur den, wo sich deine alte transparente Bitmap befand.

Allerdings wird das ganze u. U. flackern, da du zwei Bitmaps auf deine Leinwand zeichnest. Das flackert immer.

Deshalb die etwas auswendigere Methode. Bis zu der alten Position die du in die TRect speicherst, bleibt alles bei altem. Nun berechnest du die neue TRect Position (entspricht den Koordinaten des Bildes). Aus den beiden Rect-Variablen erstellst du eine gemeinsame. Ich glaube das geht mit UnionRect Funktion. Nun erstellst du eine temporäre Bitmap von der Größe deiner Leinwand, kopierst aber nur den Teil der Hintergrund-Bitmap die dem gemeinsamen Rect-Bereich entspricht. Dann zeichnest du deine transparente Bitmap auch drauf. Als letzte Aktion kopierst du den Rect-Bereich aus der transparenten auf deine Leinwand.

Diese Methode flackert nicht und du ersetzt immer nur den kleinsten nötigen Bereich.
  Mit Zitat antworten Zitat
runner

Registriert seit: 13. Jan 2006
36 Beiträge
 
#3

AW: Transparentes Bitmap verschieben

  Alt 30. Jan 2014, 10:52
Danke Popov für die Antwort. Ich habe glaube ich verstanden was du meinst.

Wann kann ich aber sicher sein das der Hintergrund korrekt dargestellt wird? Ich habe mal versucht zu warten bis das Handle des Parents gültig ist. Das ist aber nicht der Zeitpunk in dem sichergestellt ist das die Komponente auch vollständig gezeichnet wurde.
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#4

AW: Transparentes Bitmap verschieben

  Alt 30. Jan 2014, 13:59
Ich hab früher versucht in der Richtung auch was zu erstellen, so dass man das absolute Minimum zeichnen muss, verlor dann aber irgendwann das Interesse es noch weiter zu verfolgen. Was ich aus der Zeit noch weiß ist, dass man nicht so ohne weiteres zwei Grafiken gleichzeitig auf die Leinwand zeichnen kann, ohne dass es flackert. Zumindest dann nicht, wenn sich die Bereiche überschneiden. Überschneiden sie sich nicht, kann man es machen. Überschneiden sie sich, führt das zum flackern.

Somit ist eine temporäre Leinwand nötig auf der zuerst alles gezeichnet wird, was zu zeichnen ist. Um aber nicht auch Bereiche zu zeichnen die sich nicht verändert haben, muss man zuerst die Bereiche berechnen die sich verändert haben. Diese Maske legt man dann über die temporäre Leinwand und zeichnet was zu zeichnen ist. Dann überträgt man das mit der gleichen Maske auf die richtige Leinwand.

Der Grund für den Umweg über die temporäre Leinwand ist klar: zeichnet man alles direkt auf der endgültigen Leinwand, dann flackert es wegen der Überlagerung. Die temporäre Leinwand führt dazu, dass es nur eine einzige Grafik ist die zuletzt übertagen wird. Das ist natürlich ein Mehraufwand, weil man alles zuletzt zwei mal zeichnet, es verhindert aber das flackern bei Überlagerung.

Optimierung bringt dann der Clipping Bereich, also die nur das zeichnen was nötig ist. Das Problem ist aber, dass ich nichts unter Delphi gefunden habe womit ich eine Art Clipping-Maske erstellen kann. Das Einzige was da ist, ist dieser UnionRect, womit man aus zwei Rect-Bereichen einen gemeinsamen machen kann. Das Ergebnis ist aber nur ein großer Rect-Bereich, der beide kleinen Rect-Bereiche einschließt. Besser wäre eine Art Lochmaske. Hier muss man prüfen was evtl. die API bietet. Ich habe nichts gefunden, aber ich hab das vor 10 Jahren geguckt. Vielleicht gibt es inzwischen etwas.

Das Problem ist irgendwann, dass wenn man genug Rect-Bereiche hat und sie alle zusammenfasst, zuletzt der Rechtbereich von der Gräße der Leinwand da ist. Womit man sich letztendlich die Mühe sparen kann.

Wenn du also das weiter recherchierst, dann such mal nach der Möglichkeit einer Clipping-Lochmaske.
  Mit Zitat antworten Zitat
Popov
(Gast)

n/a Beiträge
 
#5

AW: Transparentes Bitmap verschieben

  Alt 30. Jan 2014, 19:11
Ich hab schon beim letzten Posting im Kopf gehabt, dass es da etwas gab, als ich von 10 Jahren mich damit beschäftigte. Aber ich war mir nicht sicher, also habe ich es nicht erwähnt.

Nun habe ich mir die OH wieder etwas genauer angeguckt und ja, es gibt etwas besseres als UnionRect, und zwar Regionen. Mit Regionen kann man eine Lochmaske erstellen. Es wird dann nicht das kleinste gemeinsame Rechteck gebildet wie bei UnionRect, sondern eine Lochmaske. Gezeichnet wird nur in die Maske, der Rest wird ignoriert.

Hier ein Beispiel mit zwei Regionen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  FilePath: String;
  Bmp: TBitmap;
  RgnGesamt, Rgn1, Rgn2: HRGN;
begin
  FilePath := 'C:\WINDOWS\Web\Wallpaper\Grüne Idylle.bmp';

  Bmp := TBitmap.Create;
  try
    Bmp.LoadFromFile(FilePath);

    RgnGesamt := CreateRectRgn(0, 0, 0, 0);
    Rgn1 := CreateRectRgn(100, 100, 200, 200);
    Rgn2 := CreateEllipticRgn(300, 300, 400, 400);
    CombineRGN(RgnGesamt, Rgn1, Rgn2, RGN_OR);

    SelectClipRgn(Canvas.Handle, RgnGesamt);
    Canvas.Draw(0, 0, Bmp);

    SelectClipRgn(Canvas.Handle, 0);
    DeleteObject(RgnGesamt);
    DeleteObject(Rgn1);
    DeleteObject(Rgn2);
  finally
    Bmp.Free;
  end;
end;
beide Regionen werden kombiniert. Mit SelectClipRgn wird dann ein Bereich erstellt in das gezeichnet werden kann.
  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 08:38 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