"waterfall" image lazarus / 39-Graphics ---------------------------------------------------------------------- Rik · 2018-10-22 13:54 Hello, I want to create an image where the lines shift down once a second and a new line is added at the top (behaves a bit like a waterfall). With the code below in a timer it is easily done, but very slow (takes about 100 ms on my computer). It should be possible to to this much faster by  moving memory blocks or using Bitmap.RawImage instead of Pixels[], but I can't figure out how. Thanks,  Rik Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i with WaterfallImage do // = TImagebegin // this works, but very slow (100 ms)  try    Picture.Bitmap.BeginUpdate(True); // without this it even takes 200 ms    for y:= Height-1 downto 1 do    begin      for x:= 0 to Width-1 do      begin        Canvas.Pixels[x,y]:= Canvas.Pixels[x,y-1];      end;    end;    for x:= 0 to Width-1 do    begin      Canvas.Pixels[x,0]:= NewLine[x];    end;  finally    Picture.Bitmap.EndUpdate(False);  end;end; ---------------------------------------------------------------------- Leledumbo · 2018-10-23 09:11 Don't use TImage for animation, see $(LazarusDir)/examples/lazintfimage for reference on how to manipulate pixels fast. ---------------------------------------------------------------------- Handoko · 2018-10-23 09:37 Quote from: Rik on October 22, 2018, 03:54:59 pmIt should be possible to to this much faster by  moving memory blocks or using Bitmap.RawImage instead of Pixels[], but I can't figure out how. Try using TImage.Picture.Bitmap.ScanLine. On my tests, it is much faster than single pixel accessing. You can find the example code here: http://forum.lazarus.freepascal.org/index.php/topic,37242 I think you will be interested to know: http://wiki.freepascal.org/Fast_direct_pixel_access ---------------------------------------------------------------------- Rik · 2018-10-23 12:12 lazintfimage is what I needed, thank you for the hint. In case someone is interested, here the code adapted for lazintfimage (takes less than 1 millisecond): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TRGBTripleArray = array[0..32767] of TRGBTriple;  PRGBTripleArray = ^TRGBTripleArray;var  x,y: word;  r1,r2: PRGBTripleArray;  Img: TLazIntfImage;begin  with WaterfallImage.Picture.Bitmap do  begin    try      Img:= CreateIntfImage;      for y:= Img.Height-1 downto 1 do // shift image 1 row down (waterfall)      begin        r1:= Img.GetDataLineStart(y-1);        r2:= Img.GetDataLineStart(y);      for x:=0 to Img.Width-1 do r2^[x]:= r1^[x];      end;      LoadFromIntfImage(Img);      BeginUpdate(True);      for x:= 0 to Width-1 do Canvas.Pixels[x,0]:= NewLine[x]; // add the new line at the top    finally      EndUpdate(False);    end;  end;end;  Regarding Bitmap.ScanLine: I thought this works only in Delphi, not in Lazarus. But GetDataLineStart does pretty much the same. ---------------------------------------------------------------------- circular · 2018-10-25 09:34 Indeed it seems GetDataLineStart works fine. I wonder though, how much time one cycle takes in total (image re-creation and display). Note that for very  quick things in milliseconds, you need to run the operation 15 times and then divide the resulting time by 15. Because the time is measured by lumps of 15 ms so if it takes 12 ms you will get either that it took 0 ms or 15 ms. I wonder if you need to free the Img object. In fact you could do a Move to copy one whole line at once: Code: Delphi  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   for y:= Img.Height-1 downto 1 do // shift image 1 row down (waterfall)    move(Img.GetDataLineStart(y-1)^, Img.GetDataLineStart(y)^, sizeof(TRGBTriple)*Img.Width );