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

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

Beitrag von CPU-Quaeler »

Hallo nachmal! ;-)

Also, ich habe mich gestern in die Streams eingelesen, und das ist für unser Vorhaben die schlankeste Methode, da nicht so viel unbenötigtes Material mitgeschleppt wird. Das Manipulieren und so weiter klappt hervorragend...aber ich habe ein Problem. zunächst der Quelltext, dann das Problem:

Code: Alles auswählen

var
     s         : TMemoryStream;
     i,l,HOffset,xres,yres:longInt;
     b:byte;
     w:word;
     st,ende,manist,maniende,drwst,drwende,savst,savende,loadst,loadende:tDateTime;
 
begin
  RamBitmap.Canvas.Brush.Color:=clred;
  RamBitmap.Canvas.Pen.Color:=clred;
  RamBitmap.Canvas.FillRect(0,0,Image1.Width,Image1.Height);
  st:=time;
  s:=tMemoryStream.Create;
  savst:=time;
  RamBitmap.SaveToStream(s);
  savEnde:=time;
  l:=s.GetSize div 2;
  s.Position:=10;
  s.ReadBuffer(HOffset,sizeof(longInt));
 
  s.Position:=18;
  s.ReadBuffer(xres,sizeof(longInt));
 
  s.Position:=22;
  s.ReadBuffer(yres,sizeof(longInt));
 
  s.Position:=28;
  s.Read(w,sizeof(word));
 
  b:=255;
  manist:=time;
  s.Position:=Hoffset;
  for i:=HOffset to l do begin
    //s.Position:=i;
    s.WriteByte(b);
  end;
  maniende:=time;
  s.Position:=0;
  loadst:=time;
  RamBitmap.LoadFromStream(s,s.GetSize);
  loadende:=time;
  s.Free;
  drwst:=time;
  Image1.Canvas.Draw(0,0,RamBitmap);
  drwEnde:=time;
  ende:=time;
 
  Showmessage('GesamtZeit: '+FloatToStr((Ende-St)*24*60*60*1000)+'  ManipulationsZeit: '+FloatToStr((maniEnde-maniSt)*24*60*60*1000)+'  DrawZeit: '+FloatToStr((drwEnde-drwSt)*24*60*60*1000)+'  SaveZeit: '+FloatToStr((savEnde-savSt)*24*60*60*1000)+'  LoadZeit: '+FloatToStr((loadEnde-loadSt)*24*60*60*1000));
end;
Das Problem an der Sache ist, wenn ich die Rambitmap NICHT an den Stream übergebe und nur ein rotes Bild zeichne, ist die Draw-Zeit nur max. 16ms bei Fullscreen auf nem 1680x1050 Monitor. Wenn ich aber das ganze an den Stream übergebe und zurückgebe, dann steigt die Drawzeit auf 300ms an...weiss einer warum??? Die Drawzeit wird ermittel zwischen drwst und drwende. Pixelformat ist immer pf24bit. Ich habe das Gefühl, als wollte er Intern Stretchdraw mit einer größeren Bildgröße benutzen. Die Manipulationszeiten für einzelne Pixel sind gegenüber der Pixels-Methode von 1200ms auf 250ms zurückgegangen bei vergleichbarem Aufwand.

Danke schonmal! :)

Edit: wenn ich RamBitmap.LoadFromStream(s,s.GetSize); weglasse und Image1.Canvas.Draw(0,0,RamBitmap); durch Image1.picture.bitmap.loadfromStream(s,s.getsize) ersetze, habe ich auf einmal nur noch die Hälfte an DrawTime (was logisch ist, da draw entfällt und Loadzeit in drawzeit wandert), allerdings merkt man, wie es einen kurzen Augenblick dauert, bis das Bild erscheint, nach dem die showmessage bereits erschienen ist. => also immer noch das gleiche Problem, nur die Zahlen sind geschönt.

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 »

CPU-Quaeler hat geschrieben:Wenn ich aber das ganze an den Stream übergebe und zurückgebe, dann steigt die Drawzeit auf 300ms an...weiss einer warum???
Ist doch Klar: Raus aus der Grafik-Karte / rein in die Garfik-Karte (genauer gesagt: "Grafik-Kontext") kostet jede Menge Zeit. Deshalb entweder das Bild komplett in der Grafikkarte bearbeiten (z.B. Texte und Flächen am Stück malen) oder komplett mit der CPU vorbereiten (Pixel malen) und dann am Stück darstellen und keinesfalls aus der Grafikkarte wieder herauslesen, sondern zum Weiterbearbeiten die Version im CPU-RAM benutzen.
-Michael

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 »

mschnell hat geschrieben:
CPU-Quaeler hat geschrieben:Wenn ich aber das ganze an den Stream übergebe und zurückgebe, dann steigt die Drawzeit auf 300ms an...weiss einer warum???
Ist doch Klar: Raus aus der Grafik-Karte / rein in die Garfik-Karte (genauer gesagt: "Grafik-Kontext") kostet jede Menge Zeit. Deshalb entweder das Bild komplett in der Grafikkarte bearbeiten (z.B. Texte und Flächen am Stück malen) oder komplett mit der CPU vorbereiten (Pixel malen) und dann am Stück darstellen und keinesfalls aus der Grafikkarte wieder herauslesen, sondern zum Weiterbearbeiten die Version im CPU-RAM benutzen.
-Michael
Aber das ist doch jetzt genau das, was ich mache. Ich Lade das Bild in den Stream, bearbeite es dort, und gebe es am Stück zurück an die Image1. Oder verstehe ich da was falsch?
Das geht ja auch viel schneller als vorher mit dem Pixels-Befehl...ich frage mich nur, warum zwischen der Rückgabe des Streams (und somit abschluss der Procedur) und der letzendlichen Darstellung ca. 300ms vergehen.

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 »

300 mSec für die Darstellung eines Pixel-Arrays ist allerdings viel zu viel. Keine Ahnung was da schief läuft.

-Michael

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 »

Also das Problem hat sich nun gelöst. Nachdem ich dieses Wochenende endlich dazu kam, mich ein bißchen einzulesen, habe ich für die LazIntfImage entschieden, die ich anfangs schlecht fand. Aber das Aufwand-Nutzen Verhältnis ist im Falle von Promathika nahezu gigantisch. Wird der Bildschirm mit Pixeln vollgekleistert, geht die reine Ausgabe-Zeit im Falle meines Systems von 1400ms auf 78ms unter Win7 runter...und das ist ein Wort. Jetzt skalliert endlich auch die Gesamt-Zeit sehr gut mit Anzahl an eingestellten Threads (das physikalische Vorhandensein von entsprechenden CPU-Kernen vorausgesetzt ^^). Und nun zur Lösung, falls es noch mehr Leute gibt, die das gleiche Problem, wie ich es hatte, haben:

Code: Alles auswählen

procedure sowieso;
  var
     ScrMaskH,ScrBufH:HBitmap;
     FpFarbe:tFPColor;
     ColBuf:tColor;
     IntfImg:tLazIntfImage;
   begin  
     ScrBufH:=Screenbuffer.Handle;   //Ein Handle des Quellbildes (Screenbuffer) muss erstellt werden. (Sone Art Object-Pointer, der auf die Bitmap zeigt und deren Infos enthält)
     ScrMaskH:=Screenbuffer.MaskHandle;  // ScreenBuffer ist TBitmap und existiert schon vorher. In diesem Falle ist z.B. das Hintergrundbild schon im Screenbuffer enthalten
     IntfImg:= TLazIntfImage.Create(0, 0);
     IntfImg.LoadFromBitmap(ScrBufH,ScrMaskH);  //Handle wird an die IntfImage übergeben und somit auch der Bildinhalt. Wenn kein Bild existiert, müssen die description und Auflösung festgelegt werden.
       //An dieser Stelle könnte eine For-Schleife beginnen, die Pixelweise das ursprungs-Bild manipuliert
           ColBuf:=clgreen;
           IntfImg.Colors[x, y] := FPColor(red(ColBuf)*256,green(ColBuf)*256,blue(Colbuf)*256);  //Hier wird Pixelweise manipuliert, wobei tColor mit 256 multipliziert werden muss, um auf tFPColor zu kommen, 
                                                                                                                                          //da eine tColor-Komponente 1byte groß ist und eine tFPColor 1word
      //hier sind die Manipulationen zu ende, sodass die IntfImage per Handle wieder an die Ursprungsbitmap zurückgegeben werden kann.
     IntfImg.CreateBitmaps(ScrBufH,ScrMaskH);  //Erzeugung von Handles, die auf die erstellte Bitmap zeigen
     Screenbuffer.Handle:=ScrBufH;  //Zuweisung der Handles zurück auf die Bitmap
     Screenbuffer.MaskHandle:=ScrMaskH;
     IntfImg.Free;  //die IntfImage kann und sollte nun freigegeben werden.
    end;
Achso, damit der Compiler keine Units vermisst, muss man noch folgende Units im Uses-Teil hinzufügen: graphtype,intfgraphics,FpImage,lcltype. Die anderen sollten Standard-mäßig drin sein, wenn man eine Image erzeugt auf der Hauptform.

Wenn ich so ein kurzes Beispiel gehabt hätte, hätte ich mir Stunden-langes Suchen und Nachvollziehen ersparen können...von daher hoffe ich, dass ich damit jemandem helfen kann :)

Danke nochmals an alle für die Hinweise!

P.s.: Wie kann man vermerken, dass der Thread "gelöst" ist?

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 »

CPU-Quaeler hat geschrieben:Wenn ich so ein kurzes Beispiel gehabt hätte, hätte ich mir Stunden-langes Suchen und Nachvollziehen ersparen können...von daher hoffe ich, dass ich damit jemandem helfen kann :)
Ähem, war das nicht meine allererste Antwort in diesem 3-Seiten Thread?

http://www.lazarusforum.de/viewtopic.php?p=32486#p32486" onclick="window.open(this.href);return false;

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: Im Prinzip hast du recht. Aber wenn man in dem Thema nicht drin ist, ist das nur ein Link zu einer Seite mit einem Wust an Informationen, von denen man erstmal nicht weiss, welche einen am besten dienen könnte, vor allem wenn man sich geistig abends nach einem Arbeitstag mit diversen Überstunden noch da reinfinden muss - ich habe mich ja auch mehrmals bedankt. Aber wirklich geholfen hat mir der Link zu dem Zeitpunkt nicht, wenn mans genau nimmt.

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

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

Beitrag von monta »

CPU-Quaeler hat geschrieben:P.s.: Wie kann man vermerken, dass der Thread "gelöst" ist?
ist hier eigentlich eher unüblich.

Manche editieren auch ihren ersten Beitrag und schreiben gelöst dahinter. (Es gibt ja keine sperre hier, wie lange ein Beitrag editiert werden darf.)
Johannes

Antworten