Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von CPU-Quaeler »

Hallo Leute!

Multi-Threading ist ja schön und gut...Promathika (ein Programm, an dem ich und Euklid schreiben) kann wirklich schnell und auf vielen Cores parallel Funktionswerte, Farbwerte, PostProcessing und mehr berechnen. Jedoch gibt es ein blödes Problem. Ich MUSS die Ergebnisse jedes Threads über den Canvas.Pixels[x,y]:=tColor auf eine Bitmap im Ram schreiben. Wenn ich alle Pixel geschrieben habe, gebe ich das ganze über einen Draw-Befehl an eine Image am Bildschirm. Das bedeutet, dass während der Pixels-Befehl in einer sehr langen Schleife wiederholend aufgerufen wird, gar nicht das Bild sehen möchte, sondern erst, wenn alles fertig ist. Ich glaube, dass der Pixels-Befehl sehr viel Overkill betreibt. Gibt es da was besseres, wenn ich Pixelweise Werte übergeben möchte? Ich habe folgendes versucht, was aber in der Fehlermeldung ausartete: "Abstract Method Called":

Code: Alles auswählen

//Relevanter Auszug aus dem Quellcode
     Widge:=tWidgetSet.Create;
     Screenbuffer.Canvas.Changing; //ScreenBuffer ist tBitmap
     HandleBuf:=Screenbuffer.Canvas.Handle; //(HandleBuf ist vom Typ HDC)
     for i:=0 to ClassDrwSet.PerformanceSet.ThreadCount-1 do begin
       ResultSize:=ResultSize+length(ErgArray[i]);
       for k:=0 to length(ErgArray[i])-1 do begin
         Widge.DCSetPixel(HandleBuf,ErgArray[i,k].Punkt.x,ErgArray[i,k].Punkt.y,ErgArray[i,k].Farbe);//<- Hier stand vorher Screenbuffer.canvas.Pixels[ErgArray[i,k].Punkt.x,ErgArray[i,k].Punkt.y]:=ErgArray[i,k].Farbe
       end;
     end;
     Screenbuffer.Canvas.Changed;
     Widge.free;
Danke schonmal im Voraus!
Gruß, Arthur

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von theo »

http://wiki.lazarus.freepascal.org/Deve ... ng_example" onclick="window.open(this.href);return false;

Socke
Lazarusforum e. V.
Beiträge: 3178
Registriert: Di 22. Jul 2008, 19:27
OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
CPU-Target: 32bit x86 armhf
Wohnort: Köln
Kontaktdaten:

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von Socke »

Du könntest dein Bild direkt im Speicher bearbeiten. Such mal nach RawImage. Da musst du dir deine Pixelpositionen und PixelFormate aber selbst berechnen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein

CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von CPU-Quaeler »

@theo: Danke, aber das funktioniert kein bißchen schneller, wenn ich nicht Zusatzkomponenten für Lazarus installiere. Und das will ich auch bis aufs letzte vermeiden, da ich da seltsame Gefühle bzw. Befürchtungen mit habe :mrgreen:
@Socke: Danke für den Tipp! Ich bin gestern auch mal darauf gestoßen. Bisher ist mir aber noch nicht klar, wie ich damit arbeiten kann. Genauer gesagt: Wie kann ich die Daten letzenendes in der Image auf dem Bildschirm ausgeben. Und wie arbeite ich generell mit diesem Objekt?...bisher war es mir gegönnt nur mit Klassen zu arbeiten. Ich wär total begeistert, wenn mir da jemand ein kurzes Einsatz-Beispiel geben könnte. :idea:

Falls sich einer traut, dem sei schon im voraus herzlich gedankt! :D

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von pluto »

Du könntest alles in ein buffer erstellen und dann per BITBLT auf den anzeige Canvans kopieren.
oder du könntest dir das mal anschauen: http://www.aggpas.org/aggpas-demo.htm" onclick="window.open(this.href);return false; ob das schneller ist oder ob das eine Altnertive für Canvasn ist weiß ich nicht, es ist aber dabei.
wenn mir da jemand ein kurzes Einsatz-Beispiel geben könnte.
Es gibt im Lazarus-Verzeichnis ein Beispiel dazu. Es nennt sich Scanline. Eventuell hilft dir das weiter. Aber das ist ein generelles Problem mit den ich bei meinem Projekt auch zu kämpfen haben, allerdings kann ich bei mir einige "Tricks" anwenden. Wie Groß ist bei dir ein Canvas ? Verwendet ihr ASM ?
MFG
Michael Springwald

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von Scotty »

Scanline wird bei Delphi immer als die schnellste Variante erwähnt. Hier eines der unzähligen Tutorials: http://www.efg2.com/Lab/ImageProcessing/Scanline.htm" onclick="window.open(this.href);return false;

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von pluto »

Ja das stimmt. Das Problem dabei ist jedoch nur, dass es sowas in Lazarus nicht gibt. Es gibt nur ein Beispiel was es zeigt wie sowas geht. Oder halt OpBitMap. ScaneLine ist glaube ich wesentlich schneller weil es Pointer nutzt. Statt ein Zwei D Array.

Es gibt wie gesagt ein Beispiel im Lazarus Ordner, wie sowas mit Lazarus-Bord-Mittel umzusetzten ist. Ich habe es jedoch damit nicht geschafft. Ein Anders Problem ist: Die Größe zu verändern. Das braucht meiner Meinung nach viel zu viel zeit. Das hängt natürlich auch mit der Pixels Eigenschaft zusammen.
MFG
Michael Springwald

CPU-Quaeler
Beiträge: 36
Registriert: So 17. Aug 2008, 00:04

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von CPU-Quaeler »

Hallo Leute!

Danke für eure Beiträge, ich werde die Vorschläge untersuchen.

Sowas wie Scanline würde mir aber nicht helfen, da man nicht vorhersehen kann, wie viele Pixel berechnet werden müssen, wenn der Benutzer eine Funktion eingibt. Die Pixelberechnung (mit Antialiasing und Postprocessing) selbst passiert in Threads. Jeder Thread übergibt einen Pointer auf einen anderen dyn. Array. Ein Array-Element enthält x,y und Farbwert.
Es kann also sein, dass von einer ganzen Zeile an Pixeln nur 2 bis 3 Pixel ausgegeben werden oder eben fast eine ganze Zeile. Weil der Graph auch wegen dem Aufbau und der Skallierbarkeit mit vielen Kernen Pixelweise berechnet werden muss, muss ich es auch so ähnlich ausgeben.

Der Canvas ist variabel und kommt der Bildschirm-Auflösung nahe bei Bedarf...bzw. im Normalfall.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von mschnell »

Auch zwei Pixel schreiben ist mit Scanline vermutlich schneller als mit dem Pixel-Array, da bei jedem Zugriff auf ein Pixel auf dem Bildschirm der Grafik-Kontext des Betriebssystems gesperrt wird, die Änderung durchgeführt und dann der Grafik-Kontext wieder freigegeben wird. Was beim Grafik-Kontext-Zugriff passiert ist Sache des Bildschirm-Treibers. U.U. wird jedesmal eine große Menge von Pixeln aus dem Grafik-Memory des Grafik-Prozessors in das Memory der CPU kopiert und nachher wieder zurück.

Bildschirm-Grafiken Pixelweise zu bearbeiten ist ein ganz schlechtes Konzept. Wenn möglich sollten Grafiken, wenn Pixel-Bearbeitung nötig ist, im Arbeitsspeicher bearbeitet werden und dann komplett zur Anzeige gebracht werden. Viel besser ist es aber, die vom Grafikprozessor zur Verfügung gestellten Pimitives zu verwenden, statt Pixel "von Hand" zu bearbeiten (siehe dazu "SDL").

-Michael

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von pluto »

SDL nutzt die GPU aber auch nur in Verbindung mit OpenGL. Da kann man auch gleich OpenGL im 2D Modus nehmen.
MFG
Michael Springwald

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von Euklid »

mschnell hat geschrieben:Bildschirm-Grafiken Pixelweise zu bearbeiten ist ein ganz schlechtes Konzept. Wenn möglich sollten Grafiken, wenn Pixel-Bearbeitung nötig ist, im Arbeitsspeicher bearbeitet werden und dann komplett zur Anzeige gebracht werden.
Wir bearbeiten die Bildschirm-Grafiken nicht pixelweise.
CPU-Quaeler hat geschrieben:Ich MUSS die Ergebnisse jedes Threads über den Canvas.Pixels[x,y]:=tColor auf eine Bitmap im Ram schreiben. Wenn ich alle Pixel geschrieben habe, gebe ich das ganze über einen Draw-Befehl an eine Image am Bildschirm.
- Euklid

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von theo »

@Euklid
Canvas.Pixels[x,y]:=tColor
ist pixelweise Bearbeitung der Bildschirm Grafik.

Ich persönlich verstehe aber nicht ganz, was ihr eig. erreichen wollt. Könnt ihr das besser erklären?

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von Euklid »

Es handelt sich um die Canvas einer Bitmap (vom Typ tBitmap), die lokal erzeugt wird und nur im Arbeitsspeicher existiert. Ich verstehe nicht, weshalb für diesen reinen Speicherzugriff der Grafik-Kontext des Betriebssystems gesperrt werden müsste?

Benutzeravatar
theo
Beiträge: 10871
Registriert: Mo 11. Sep 2006, 19:01

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von theo »

Das Problem an Canvas.Pixels[x,y]:=clblack; ist, dass es bei jedem Aufruf/Pixel das Widgetset (evtl. sog. X) bemühen muss.
z.B. GTK

Code: Alles auswählen

procedure TGtkWidgetSet.DCSetPixel(CanvasHandle: HDC; X, Y: integer; AColor: TGraphicsColor);
var
  DC     : TGtkDeviceContext absolute CanvasHandle;
  DCOrigin: TPoint;
  GDKColor: TGDKColor;
begin
  if (DC = nil) or (DC.Drawable = nil) then exit;
 
  DCOrigin := DC.Offset;
  inc(X,DCOrigin.X);
  inc(Y,DCOrigin.Y);
 
  DC.SelectedColors := dcscCustom;
  GDKColor := AllocGDKColor(AColor);
  gdk_gc_set_foreground(DC.GC, @GDKColor);
  {$IFDEF DebugGDK}BeginGDKErrorTrap;{$ENDIF}
  gdk_draw_point(DC.Drawable, DC.GC, X, Y);
  {$IFDEF DebugGDK}EndGDKErrorTrap;{$ENDIF}
end;
Unter "im Arbeitsspeicher arbeiten" verstehe ich was anderes.
z.B. OpBitmap schreibt nur einen Wert in ein Array statt externe Library Funktionen aufzurufen.

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Re: Gibt es etwas schnelleres als Pixels[x,y]:tColor?

Beitrag von Euklid »

Ok, verstehe. Dann ist es kein Wunder, dass Pixels relativ langsam arbeitet....
Wir würden gerne soweit wie mögliche Unabhängigkeit von externen Komponenten bewahren. Ist meine Annahme richtig, dass mit tlazintfimage ein direkterer Zugriff möglich ist?

Antworten