[Lazarus] Fast drawing to canvas

Sven Barth pascaldragon at googlemail.com
Wed Feb 8 17:12:36 CET 2012


Am 08.02.2012 16:02, schrieb dhkblaszyk at zeelandnet.nl:
> I have played with Image.Update, .Invalidate and .Repaint, but none of
> them seem to work for me. Only when I put Application.ProcessMessages
> the painted images show on screen. See below for the testloop code. The
> images are streamed from a file cache. For 24 frames this seems
> overkill, but running at 24fps the memeory requirements quickly get very
> large!
>
> Image.Transparent is also set to false btw, which is default. Otherwise
> the drawing on the canvas is even messed up.
>
> Regards, Darius
>
> procedure TForm1.Button1Click(Sender: TObject);
> var
> s: TDateTime;
> i: Integer;
> begin
> s := now;
> for i := 1 to 24 do
> begin
> if filecache_get_from_cache(i, png) then
> begin
> Image1.Picture.Bitmap.LoadFromRawImage(png.RawImage, False);
> Application.ProcessMessages;
> end;
> end;
>
> ShowMessage(FloatToStr(24 / ((now - s) * 24 * 3600)))
> end;

Here it is clear that you need to use Application.ProcessMessages, 
because "LoadFromRawImage" will only tell the control that it needs to 
repaint itself, but does not execute this repainting (this is done in 
Application.ProcessMessages). In the example you posted in the beginning 
the call to Application.ProcessMessages is located inside the OnPaint 
handler of the Image which is - in my opinion - not good. Maybe also the 
loading of the image inside the OnPaint handler is not good...

Maybe you should try - like Felipe suggested - something else than 
TImage. Try for example TPaintBox in combination with the 
Application.OnIdle event:

procedure TForm1.ApplicationOnIdle(aSender: TObject; var aDone: Boolean);
begin
   LoadNextImageFromCache; // this will load the next image into some 
private variable of the form (let's call it fImage). [this is based on 
your filecache_get_from_cache any you'll need to write it of course ;) ]
   PaintBox1.Invalidate;
   aDone := False; // important!
end;

procedure TForm1.PaintBox1Paint(aSender: TObject);
begin
   PaintBox1.Canvas.Draw(fImage); // or however you'll get the content 
of the fImage onto the canvas of the PaintBox
end;

Note: Don't forget to assign your ApplicationOnIdle to 
Application.OnIdle or use the ApplicationProperties component located in 
the Additional tab.

Regards,
Sven




More information about the Lazarus mailing list