how to make canvas faster

I plot some rect graphic in bmp and then plot in image.canvas and test the speed.The result is not  good enough.It need 300ms inmy pc. I have use api to replace  delphi canvas .but api only faster about 10% than delphi canvas.it could improve?  my test example below:

procedure Ttest.Button1Click(Sender: TObject);
var       I:INTEGER;con:tcontrol;pbase:tpoint;rstart,rend,fre:int64;
          myrect:trect;
begin
     Randomize;
     myrect.left:=0;
     myrect.Top :=0;
     myrect.Right  :=900;
     myrect.Bottom :=900;
     myimage.Visible :=false;
     MYbmp.Width :=900;
     MYbmp.Height :=900;
     MYBMP.PixelFormat:=PF8BIT;//
     QueryPerformanceCounter(rstart);//TEST TIME START
     QueryPerformanceFrequency(fre);
     for i:=0 to 2499 do begin
           rect1[i].left:= random(400);
           rect1[i].Top:= random(900);
           rect1[i].Right:= random(900);
           rect1[i].Bottom := random(900);
           mybmp.Canvas.Brush.Color :=rgb(random(900),random(900),random(900));
           mybmp.canvas.Rectangle(rect1[i]);//PLOT RECTANGLE
         end;
      myimage.Canvas.CopyRect(myrect,MYbmp.Canvas ,myrect );
      QueryPerformanceCounter(rend););//TEST TIME END
      self.Caption := floattostr(((rend-rstart)/ fre )* 1000);









Cheng_samAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

KunfufaresiCommented:
Hello,

you should crate a secondary canvs. then paint on it and after that copy that canvas over the other one. this will deffinitly be faster as the painting will be virtual. Is your mybmp a visual component or nonvisul runtime created component.

Ekim
monirCommented:
HI,

In form create use DoubleBuffered:=true

When DoubleBuffered is False, the windowed control paints itself directly to the window. When DoubleBuffered is True, the windowed control paints itself to an in-memory bitmap that is then used to paint the window. Double buffering reduces the amount of flicker when the control repaints, but is more memory intensive.

Cheng_samAuthor Commented:
mybmp is tbitmap. I have draw all graphic in mybmp and then plot it in image. I set form.DoubleBuffered:=true it seems don't any improve.  
Exploring ASP.NET Core: Fundamentals

Learn to build web apps and services, IoT apps, and mobile backends by covering the fundamentals of ASP.NET Core and  exploring the core foundations for app libraries.

monirCommented:
To get more speed, use DirectX instead of Canvas.
monirCommented:
I saw an a good answer here about how to make bitblt faster, the answer was by change something related to graphics  card in control panle, maybe it will helps you, I searched for the article and I failed to find it.
KunfufaresiCommented:
{===============================================================================
===============================================================================}
unit EnhBitmaps;

interface

uses
  Windows, Graphics;

type
  TEnhBitmap = class(TBitmap)
  public
    X1: Integer;
    Y1: Integer;
    constructor Create; override;
    procedure LineTo(const X2: Integer;
                     const Y2: Integer);
    procedure MoveTo(const X2: Integer;
                     const Y2: Integer);
  end;

implementation

uses
  Math;

{===============================================================================
===============================================================================}
constructor TEnhBitmap.Create;

begin
  inherited;

  PixelFormat := pf32Bit;
end;

{===============================================================================
This procedure draws a line very quickly (compared to Canvas.LineTo).

To enhance speed, references to ScanLine and Canvas.PenPos were minimized,
and
the code assumes PixelFormat = pf32Bit (pixels are treated as 32-bit
integers).

All loops were semi-unrolled to process pixels in pairs; this has several
benefits:

(1) The loop counters are tested half as often as they otherwise would be.
(2) The if statement within the diagonal line loop is also tested half as
often.
(3) The lines are guaranteed to be symmetrical.
(4) Modern processors can pair up the pixel operations and execute them
    simultaneously since they are not dependent on each other.
===============================================================================}
procedure TEnhBitmap.LineTo(const X2: Integer;
                            const Y2: Integer);

var
  DX: Integer;             // X-dimension of the line segment
  DY: Integer;             // Y-dimension of the line segment

  Delta: Integer;          // total distance remaining to next minor axis
  Epsilon: Integer;        // aspect ratio of the line segment

  Index: Integer;          // loop counter

  Pixel1: PInteger;        // pixel pointers
  Pixel2: PInteger;

  RowOffset: Integer;      // pointer offset for adjacent rows
  MajorOffset: Integer;    // = ±RowOffset or ±ColOffset as appropriate
  MinorOffset: Integer;    // = ±RowOffset or ±ColOffset as appropriate
  DiagonalOffset: Integer; // = MajorOffset + MinorOffset for 45° angles

  Count: Integer;          // number of pixel pairs in the line segment

const
  ColOffset = 1;           // pointer offset for adjacent columns

begin
  if (X1 < 0) or (X1 >= Width) or
     (X2 < 0) or (X2 >= Width) or
     (Y1 < 0) or (Y1 >= Height) or
     (Y2 < 0) or (Y2 >= Height) then
    begin
    MoveTo(X2, Y2);
    Exit;
    end;

  DX := Abs(X2 - X1);
  DY := Abs(Y2 - Y1);

  RowOffset := -Width;

  if (DX > DY) then
    begin
    if (X1 < X2) then
      MajorOffset := ColOffset
    else
      MajorOffset := -ColOffset;

    if (Y1 < Y2) then
      MinorOffset := RowOffset
    else
      MinorOffset := -RowOffset;
    end
  else
    begin
    if (Y1 < Y2) then
      MajorOffset := RowOffset
    else
      MajorOffset := -RowOffset;

    if (X1 < X2) then
      MinorOffset := ColOffset
    else
      MinorOffset := -ColOffset;
    end;

  Pixel1 := ScanLine[0];
  Pixel2 := Pixel1;

  Inc(Pixel1, Y1 * RowOffset + X1 * ColOffset);
  Inc(Pixel2, Y2 * RowOffset + X2 * ColOffset);

  Count := Max(DX, DY) shr 1;

  if ((DX = 0) or (DY = 0)) then
    for Index := 0 to Count do
      begin
      Pixel1^ := 0;
      Pixel2^ := 0;

      Inc(Pixel1, MajorOffset);
      Dec(Pixel2, MajorOffset);
      end
  else
    if (DX = DY) then
      begin
      DiagonalOffset := MajorOffset + MinorOffset;

      for Index := 0 to Count do
        begin
        Pixel1^ := 0;
        Pixel2^ := 0;

        Inc(Pixel1, DiagonalOffset);
        Dec(Pixel2, DiagonalOffset);
        end;
      end
    else
      begin
      Epsilon := (Min(DX, DY) shl 16) div Max(DX, DY);
      Delta := 0;

      for Index := 0 to Count do
        begin
        Pixel1^ := 0;
        Pixel2^ := 0;

        Inc(Pixel1, MajorOffset);
        Dec(Pixel2, MajorOffset);

        Inc(Delta, Epsilon);

        if (Delta >= $8000) then
          begin
          Dec(Delta, $10000);

          Inc(Pixel1, MinorOffset);
          Dec(Pixel2, MinorOffset);
          end;
        end;
    end;

  MoveTo(X2, Y2);
end;

{===============================================================================
===============================================================================}
procedure TEnhBitmap.MoveTo(const X2: Integer;
                            const Y2: Integer);

begin
  X1 := X2;
  Y1 := Y2;
end;

end.

i found this havent tested it or really looked ovre the code it says it is faster than usual maybe it can be addapted to your situation. although this is moveto and lineto.

source is
http://homepages.borland.com/efg2lab/Library/Delphi/Graphics/GaryWillilams_EnhBitmap.TXT

http://homepages.borland.com/efg2lab/Library/Delphi/Graphics/Algorithms.htm
KunfufaresiCommented:
also you use MYBMP.PixelFormat:=PF8BIT;// but you use full rgb palette. this might be slowing things down as delphi has to convert 24bit to 8bit in some fashion for each loop.
KunfufaresiCommented:
on last link

http://torry.net/authorsmore.php?id=2499&SID=5a6ee3f366fdf7faa4e8559e6d8d5440

very fast bitmap unit graph64 it is really fast i used it before, although i needed it for canvas filters.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Cheng_samAuthor Commented:

I have tried TEnhBitmap.

     fast_bmp:=TEnhBitmap.Create ;
     fast_bmp.Width :=900;
     fast_bmp.Height :=900;
    with fast_bmp.Canvas do begin
          for i:=0 to 1000 do begin
              PEN.Color :=CLred;
              pen.Width :=2;
              fast_bmp.MoveTo(rect1[i].Left,rect1[i].Top);
              fast_bmp.LineTo(rect1[i].Right,rect1[i].Bottom);
          end;

    it can't  be  run. it show  error message   when run to "fast_bmp.LineTo".why?
Slick812Commented:
hello  Cheng_sam , , I looked at your code above and I did not understand some of the things you did there. . .
I beleive that there is a BIG speed difference if you set a TBitmap to a Pixel format, as in -

MYBMP.PixelFormat:=PF8BIT;

if you create a TBitmap and DO NOT change the Pixel format, it will run mant times Faster

     MYbmp := TBitmap.Create; // makes a bitmap that works faster
     MYbmp.Width :=900;
     MYbmp.Height :=900;
   
     QueryPerformanceCounter(rstart);//TEST TIME START
     QueryPerformanceFrequency(fre);
     for i:=0 to 2499 do begin
           rect1[i].left:= random(400);
           rect1[i].Top:= random(900);
           rect1[i].Right:= random(900);
           rect1[i].Bottom := random(900);
           mybmp.Canvas.Brush.Color :=rgb(random(255),random(255),random(255));
           mybmp.canvas.Rectangle(rect1[i]);//PLOT RECTANGLE
         end;

      MYBMP.PixelFormat:=PF8BIT; // change the pixel format here AFTER rect draw
// or Better still, do NOT change the pixel format
      myimage.Canvas.CopyRect(myrect,MYbmp.Canvas ,myrect );
      QueryPerformanceCounter(rend););//TEST TIME END
      self.Caption := floattostr(((rend-rstart)/ fre )* 1000);


 = = = = = = = = = = = = = = = = = = = = =

I have some questions, , 1: Why do you use an 8 bit bitmap for  this? ?
2: Why do you draw so many rectangles ?, in  my tests for this, the last 200 or 300 rectangles covered ALL of the 2000 rectangles drawn before, ,if you really want faster drawing then reduce the number of rectangles, in my tests this -
   for i:=0 to 512 do begin

gave me the same Look as the 2499 did. . .

3: , I do not understand whty you did this -
    rgb(random(900),random(900),random(900))

should this be -
    rgb(random(255),random(255),random(255))

4: what are you trying to do here with this, there may be a way to speed it up, with other methods, ,


if you like I can show you code for API for this

? ? ?
Cheng_samAuthor Commented:
8 bit bitmap is only for speed up.    rgb(random(255),random(255),random(255)) is a correct interval.
We can use canvas plot  line or others.  Plot rectangle is for test .
I have used api for test . it is below:

procedure Ttest.Button1Click(Sender: TObject);
var  MemDC: HDC;i:integer; myrect:trect;mydc:hdc;
    MemBmp,oldbmp: HBITMAP;  mypen:hpen;image_handle: thandle;
begin
     mydc:=getdc(self.Handle );
     memdc:= CreateCompatibledc(mydc);
     oldbmp:=CreateCompatibleBitmap(mydc,900,900);
     MemBmp := SelectObject(MemDC, oldbmp);

     QueryPerformanceCounter(rstart);
     QueryPerformanceFrequency(fre);
     for i:=0 to 2499 do begin
          rect1[i].left:= random(900);
          rect1[i].Top:= random(900);
          rect1[i].Right:=random(900);
          rect1[i].Bottom :=random(900);
          mypen:= createpen(ps_solid,2,clred);
          selectobject(memdc,mypen);
          movetoex(memdc,rect1[i].Left ,rect1[i].Top,nil );
          lineto(memdc,rect1[i].Right ,rect1[i].Top );
          DeleteObject(mypen);

          mypen:= createpen(ps_solid,2,clgreen);
          selectobject(memdc,mypen);
          movetoex(memdc,rect1[i].Right ,rect1[i].Top ,nil);
          lineto(memdc,rect1[i].Right ,rect1[i].Bottom);
          DeleteObject(mypen);

          mypen:= createpen(ps_solid,2,clblue);
          selectobject(memdc,mypen);
          movetoex(memdc,rect1[i].Right ,rect1[i].Bottom,nil  );
          lineto(memdc,rect1[i].Left ,rect1[i].Bottom);
          DeleteObject(mypen);

          mypen:= createpen(ps_solid,2,clgray);
          selectobject(memdc,mypen);
          movetoex(memdc,rect1[i].Left ,rect1[i].Bottom,nil  );
          lineto(memdc,rect1[i].Left ,rect1[i].Top );
          DeleteObject(mypen);
     end;
     DeleteObject(MemBmp);
     DeleteObject(oldBmp);
     myrect.left:=0;
     myrect.Top :=0;
     myrect.Right  :=900;
     myrect.Bottom :=900;
     bitblt(mydc ,0,0,900,900,memdc,0,0,SRCcopy);
     QueryPerformanceCounter(rend);
     self.Caption := floattostr(((rend-rstart)/ fre )* 1000);
 end;
 
Cheng_samAuthor Commented:
Slick812 would show your API code?Thanks.
Slick812Commented:
I am now confused, ? ? and do not understand what you are trying to do? Or the purpose of this code?
In your last post, you are drawing lines, not rectangles ( although the lines look as if they form rectangles). . . .

I can not see why you want to draw 2500 rectangles on a 900x900 bitmap, when less than 300 rectangles are visible when you finish the rectngle drawing, , the more rectangles you draw, the more time it takes, so if you want to use less time, then draw fewer rectangles. . .
If your 8 bit DIB is only for speed, then in my tests a DDB ( Compatable Bitmap ) was always faster for drawing rectangles. . .

OK, if you only want speed, then use the folowing code -


procedure TForm2.ButtonCompBmpClick(Sender: TObject);
var
hBmpComp, BmpDC, oBr, i, fmDC: Cardinal;
rstart, rend, fre: Int64;
begin
Randomize;
QueryPerformanceFrequency(fre);
QueryPerformanceCounter(rstart);//TEST TIME START
BmpDC := GetDC(0);
hBmpComp := CreateCompatibleBitmap(BmpDC, 900, 900);
// the DDB from the CreateCompatibleBitmap function, will usually give faster draw
ReleaseDC(0, BmpDC);
BmpDC := CreateCompatibleDC(0); // you MUST call DeleteDC for BmpDC
SelectObject(BmpDC, hBmpComp); // there is NO bitmap in this DC, so you do NOT need to get a result

oBr := SelectObject(BmpDC, CreateSolidBrush(RGB(random(255),random(255),random(255))));
// I draw 4 rectangles just to fill the bitmap, but this is just for me, you can leave this out
Rectangle(BmpDC,0,0,450,450);
// IMPORTANT in API graphic objects, you must make sure you ALWAYS Delete the created object
DeleteObject(SelectObject(BmpDC, CreateSolidBrush(RGB(random(255),random(255),random(255)))));
Rectangle(BmpDC,450,0,450,450);
for i := 0 to 1 do
  begin
  DeleteObject(SelectObject(BmpDC, CreateSolidBrush(RGB(random(255),random(255),random(255)))));
  Rectangle(BmpDC,i*450,450,450,450);
  end;

{ In my tests I did not see any difference in visual appearence between the 512
 rectangle draw and the 2499 rectangle draw, so to save time, I used 512 instead of 2499
 however, if you only want fast time, you can reduce it to -
 for i:= 0 to 270 do }

//for i:= 0 to 2499 do
for i:= 0 to 512 do
  begin
  DeleteObject(SelectObject(BmpDC, CreateSolidBrush(RGB(random(255),random(255),random(255)))));
  Rectangle(BmpDC,random(450),random(900),random(900),random(900));
  end;

DeleteObject(SelectObject(BmpDC, oBr));
fmDC := GetDC(Handle);
// this BitBlt will draw the * bit bitmap on this Form
BitBlt(fmDC, 0, 0, 900, 900, BmpDC, 0, 0, SRCCOPY);
ReleaseDC(Handle, fmDC);
DeleteDC(BmpDC);
DeleteObject(hBmpComp);
QueryPerformanceCounter(rend);//TEST TIME END
Caption := floattostr(((rend-rstart)/ fre )* 1000);
end;
Slick812Commented:
?? I did this for an 8 bit DIB, thinking that was a requirement, So this is what I would do for speed with an 8 Bit DIB , , , but it is more code here than you may want to deal with, , the code starts with the button Click-
procedure TForm2.Faster8BitClick(Sender: TObject);

 - - - -




procedure ByteSwapColors(var Colors; Count: Integer);
var   // convert RGB to BGR and vice-versa.  TRGBQuad <-> TPaletteEntry
  SysInfo: TSystemInfo;
begin
  GetSystemInfo(SysInfo);
  asm
        MOV   EDX, Colors
        MOV   ECX, Count
        DEC   ECX
        JS    @@END
        LEA   EAX, SysInfo
        CMP   [EAX].TSystemInfo.wProcessorLevel, 3
        JE    @@386
  @@1:  MOV   EAX, [EDX+ECX*4]
        BSWAP EAX
        SHR   EAX,8
        MOV   [EDX+ECX*4],EAX
        DEC   ECX
        JNS   @@1
        JMP   @@END
  @@386:
        PUSH  EBX
  @@2:  XOR   EBX,EBX
        MOV   EAX, [EDX+ECX*4]
        MOV   BH, AL
        MOV   BL, AH
        SHR   EAX,16
        SHL   EBX,8
        MOV   BL, AL
        MOV   [EDX+ECX*4],EBX
        DEC   ECX
        JNS   @@2
        POP   EBX
    @@END:
  end;
end;

procedure FillColorArray(pColor: PDWord);
var
cR, cG, cB: Cardinal;
begin
// ths will fill the Color Array with the "Netscape" 256 color pallete
for cR := 0 to 5 do
  for cG := 0 to 5 do
    for cB := 0 to 5 do
      begin
      pColor^ := (51 * cB) or ((51 * cG) shl 8) or ((51 * cR) shl 16);
      Inc(pColor);
      end;

for cR := 1 to 31 do
  begin
  pColor^ := (8 * cR) or ((8 * cR) shl 8) or ((8 * cR) shl 16);
  Inc(pColor);
  end;

pColor^ := $FFB400;
end;


function Make8BitDib(Width, Height, FillColor: Cardinal; pColorArray: Pointer): THandle;
type
  PBitmapInfo256 = ^TBitmapInfo256;
  TBitmapInfo256 = packed record
    bmiHeader: TBitmapInfoHeader;
    bmiColors: array[Byte] of Cardinal;
  end;

var
BmpDC, oBr: Cardinal;
BitInfo256: TBitmapInfo256;
pBits: Pointer;
begin
ZeroMemory(@BitInfo256.bmiHeader, sizeOf(BitInfo256.bmiHeader));
with BitInfo256.bmiHeader do
  begin
  biSize := sizeOf(BitInfo256.bmiHeader);
  biBitCount := 8;
  biCompression := BI_RGB;
  biClrUsed := 256;
  biClrImportant := biClrUsed;
  biWidth := Width;
  biHeight := Height;
  biXPelsPerMeter := 72;
  biYPelsPerMeter := 72;
  biPlanes := 1;
  end;

FillColorArray(pColorArray);
CopyMemory(@BitInfo256.bmiColors, pColorArray, SizeOf(BitInfo256.bmiColors));
ByteSwapColors(BitInfo256.bmiColors, 256);
pBits := nil;
BmpDC := CreateCompatibleDC(0);
Result := CreateDIBSection(BmpDC, PBitmapInfo(@BitInfo256)^, DIB_RGB_COLORS, pBits, 0, 0);
if Result = 0 then
  begin
  DeleteDC(BmpDC);
  Exit;
  end;
SelectObject(BmpDC, Result);
oBr := SelectObject(BmpDC, CreateSolidBrush(FillColor));
PatBlt(BmpDC,0,0,Width, Height, PATCOPY);
DeleteObject(SelectObject(BmpDC, oBr));
DeleteDC(BmpDC);
end;



procedure TForm2.Faster8BitClick(Sender: TObject);
var
aryColor256: Array[Byte] of Cardinal;
BmpWidth, BmpHeight, hBmpComp, hBmp8, BmpDC, b8DC, oBr, i, fmDC: Cardinal;
rstart, rend, fre: Int64;
begin
BmpWidth := 900;
BmpHeight := 900;
Randomize;

{ a Device Dependent Bitmap made by CreateCompatibleBitmap will most of
 the time, do drawing operation faster than a DIB,
 but this will vary because of hardware and system settings }
BmpDC := GetDC(0);
hBmpComp := CreateCompatibleBitmap(BmpDC, BmpWidth, BmpHeight);
ReleaseDC(0, BmpDC);
if hBmpComp = 0 then
  begin
  ShowMessage('ERROR - Could Not Create the Device Dependent Bitmap');
  Exit;
  end;

{for an 8 Bit Bitmap I do NOT use the full spectrum of Colors for the brush
colors random selection, I use just the 256 colors of the bitmap's palette.
theese colors are stored in the aryColor256 Array}

hBmp8 := Make8BitDib(BmpWidth, BmpHeight, $CCCC33, @aryColor256);

{the Make8BitDib function creates an 8 Bit DIB the size of the width and Height
 parameters, It makes the pallete colors as a "Netscape" 256 palette
 and gets the palette colors in the aryColor256 array as GBR}

if hBmp8 = 0 then
  begin
  DeleteObject(hBmpComp);
  ShowMessage('ERROR - Could Not Create the 8 bit DIB');
  Exit;
  end;

QueryPerformanceFrequency(fre);
QueryPerformanceCounter(rstart);//TEST TIME START

BmpDC := CreateCompatibleDC(0);
SelectObject(BmpDC, hBmpComp);
{in my system the rectangle draw was much faster on a DDB than an 8 Bit DIB}

b8DC := BmpWidth div 2;
oBr := SelectObject(BmpDC, CreateSolidBrush(aryColor256[random(255)]));
Rectangle(BmpDC,0,0,b8DC,b8DC);
// IMPORTANT in API graphic objects, you must make sure you ALWAYS Delete the created object
DeleteObject(SelectObject(BmpDC, CreateSolidBrush(aryColor256[random(255)])));
Rectangle(BmpDC,b8DC,0,b8DC,b8DC);
for i := 0 to 1 do
  begin
  DeleteObject(SelectObject(BmpDC, CreateSolidBrush(aryColor256[random(255)])));
  Rectangle(BmpDC,i*b8DC,b8DC,b8DC,b8DC);
  end;

{ In my tests I did not see any difference in visual appearence between the 512
 rectangle draw and the 2499 rectangle draw, so to save time, I used 512 instead of 2499 }

//for i:= 0 to 2499 do
for i:= 0 to 512 do
  begin
  DeleteObject(SelectObject(BmpDC, CreateSolidBrush(aryColor256[random(255)])));
  Rectangle(BmpDC,random(b8DC),random(BmpWidth),random(BmpHeight),random(BmpHeight));
  end;

DeleteObject(SelectObject(BmpDC, oBr));

b8DC := CreateCompatibleDC(0);
SelectObject(b8DC, hBmp8);
// this draws the Compatable Bmp on the 8 Bit bitmap
BitBlt(b8DC, 0, 0, BmpWidth, BmpHeight, BmpDC, 0, 0, SRCCOPY);
DeleteDC(BmpDC);
DeleteObject(hBmpComp);

fmDC := GetDC(Handle);
// this BitBlt will draw the * bit bitmap on this Form
BitBlt(fmDC, 0, 0, BmpWidth, BmpHeight, b8DC, 0, 0, SRCCOPY);
ReleaseDC(Handle, fmDC);

DeleteDC(b8DC);
DeleteObject(hBmp8);

QueryPerformanceCounter(rend);//TEST TIME END
Caption := floattostr(((rend-rstart)/ fre )* 1000);
end;
Slick812Commented:
and you do NOT need to call   Randomize , but   one  time, maybe in the initialization, or Form's OnCreate event
Cheng_samAuthor Commented:
Thank Slick812's two example. I test boths .The first one is faster 2% than use canvas.
The second is  slower than the first one. the second one ,it need more graphic skill . but why it is slower?
Slick812Commented:
???
Not sure about what you mean from your question -
    but why it is slower?

of course it is slower, if you look at the code, first there is MUCH more code, in general (but not always) if you have more code then it takes longer to process, , and in this case, I am using an 8 Bit DIB, which slows down the processing, maybe you can ask a question about a certain part of that code, there is so much there I can not make an explanation of ALL of the code.

. . . . . . .
some comment on the speed. the rectangle drawing for 2500 rectangles of large and small sizes, is going to take time, no matter what you do or how you do it, the canvas is just a "Wrapper" for the window system API device context functions, so the Canvas in many operations will be only a little slower than calling the the API functions, please notice that the Canvas will also call API functions (usually the same functions) to do drawing operations. . .

Can you please tell me why you are drawing 2500 rectangles on a bitmap, and why you need it to be faster ? ?. .

as I said before, if you need faster, then draw less rectangles
Cheng_samAuthor Commented:
I draw some graphic using cad . cad have  a high speed even graphic object  over 10000 rectangle(line)  .
draw 2500 rectangle is for test speed.and  delphi canvas (or other tool) seems  don't enough fast.
Maybe cad use other method or alogorithym.
Slick812Commented:
I still do not know why you do it?, , Just a speed test I guess, , with no use for the bitmap with rectangles on it?
I am not familar with any CAD programs, so I can not help you with anything about CAD. . . .
You may be able to draw the rectangles faster without filling them with color (use a brush as I did), but this is all I know to have speed with filled rect
Cheng_samAuthor Commented:
 I think use OpenGL or directX is another solution.   it maybe need more time to get it . thank for Slick812, Kunfufaresi and other experts' comment.  
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.