0

I have an array of record with 3 member ( bitmap path , x , y ) .

I have to after load values in record draw bitmap on Form canvas by x , y .

I tried with this code :

const
  MAXX = 40 ;
type
  ImgObj = record
    Addrs : string;
    X: Integer ;
    Y: Integer ;
  end;
var
  All : array[1..MAXX] of ImgObj ;

procedure TForm1.btn1Click(Sender: TObject);
var
  BuffBitmap :TBitmap ;
  I,j,k: Integer;
begin
  // set  all bit maps
  ....
  // draw 40 images
  BuffBitmap := TBitmap.Create ;
  for I := 1 to MAXX do
  begin
    BuffBitmap.LoadFromFile(All[i].Addrs);
    for j := 0 to BuffBitmap.Width-1 do
      for k := 0 to BuffBitmap.Height-1 do
      begin
        Self.Canvas.Pixels[All[i].X+j,All[i].Y+k] := BuffBitmap.Canvas.Pixels[j,k] ;
      end;
  end;

  BuffBitmap.free;
end;

This code draw them well , but in long time about 8 sec . and I must repeat this event more in my app.

Now how I can go to fastest way for draw 40 images on canvas.

  • Should I store bitmpas on memory for repeat ?
  • Should I user pointer for draw images ?
  • Or should I use threads for fastest draw ?

Please tell me with samples thanks.

Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
A1Gard
  • 4,070
  • 4
  • 31
  • 55
  • 1
    Drawing to individual pixels on the canvas is inefficient. This is presumably because the canvas will refresh for EACH pixel you draw. You will only want to refresh once the entire image has been copied over. Take a look at this: http://www.programmersheaven.com/mb/Delphi/110783/110783/tcanvas/ where it's recommended that you use the ScanLine procedure. – AudioGL Jun 28 '13 at 19:48
  • @AudioGL, well, yes and not really. Besides of inefficiency of atomic operation (as opposed to batch op.) it uses WinGDI's GetPixel/SetPixel which are known to be slow by themselves. – OnTheFly Jun 29 '13 at 01:41
  • There could be better ways to do this depending on the nature of the bitmaps, such as whether they are all the same size, whether they need to be loaded from files vs. from a resource, and how often this needs to be done. – MikeD Jun 29 '13 at 14:08

1 Answers1

3

Use the Draw method:

BuffBitmap.LoadFromFile(All[i].Addrs);
Self.Canvas.Draw(All[i].X, All[i].Y, BuffBitmap);
Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
  • Thanks, I choose universal way , if I want draw part of one bitmap I can't use this way . – A1Gard Jun 28 '13 at 19:36
  • 3
    @MahdiParsa, Uwe presented the most efficient way. If you want to do part of a bitmap (not indicated in your original question), you could crop the bitmap first using a function described, for example, here: http://stackoverflow.com/questions/9183524/delphi-how-do-i-crop-a-bitmap-in-place – lurker Jun 28 '13 at 19:57
  • 1
    There is also Canvas.CopyRect you can use with BuffBitmap.Canvas as source. You will have to determine the rectangles, which even gives you the ability to scale. – Uwe Raabe Jun 28 '13 at 20:07