Solved

Canvas.LineTo on TImage very SLOW

Posted on 2002-06-27
6
573 Views
Last Modified: 2010-05-18
Hello, I'm trying to make a tool to get the distance from
a point to another in a map (TImage). I click on the map
then a line moves from that first point to wherever the
mouse moves over the map until the next click.
To do so I make a copy of the original bitmap in another
and copy that one to the TImage after every move of the
mouse to repaint the line to the new position.

This works fine on the comp I'm working, AMD K6-650 with a poor S3 4mb card in windows XP PRO; however I tried
the program in a P3 1Ghz gf2mx200 32mb also in Win xp PRO and it was slow as hell, the new line takes ages to repaint; we tried it as well in our laptop, k6 500 or so and same happened, well it was a bit faster.

Any clue what's happening or a better way to do it ?


Some of the code:

procedure TMaps.DistImageMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbRight) and DistEnabled then
 begin
  // Finish
  DistEnabled:= False;
  DistImage.Canvas.Draw(0,0,DistImgTmp);
  Label51.Caption:= 'Marque un punto inicial con el ratón sobre el mapa.';
  Label52.Caption:= Format('%d km.',[TotalDist]);
  Exit;
 end;
if (not DistEnabled) and (Button = mbLeft) then // Start Straight Lining
 begin
  DistImage.Canvas.Draw(0,0,DistOrig);
  DistImgTmp.Canvas.Draw(0,0,DistImage.Picture.Graphic);
  TotalDist:= 0;
  DistEnabled:= True;
  DistImgX:= x;
  DistImgY:= y;
  Label51.Caption:= 'Marque los puntos consecuentes del recorrido a medir.'+#13#10+
                      'Para finarlizar puse el boton derecho del ratón.';
  DistImage.Canvas.Brush.Color:= clLime;
  DistImage.Canvas.Brush.Style:= bsDiagCross;
  DistImage.Canvas.Pen.Width:= 3;
  DistImage.Canvas.Pen.Color:= clLime;
  DistImage.Canvas.MoveTo(DistImgX, DistImgY);
  Exit;
 end;
if (DistEnabled) and (Button = mbLeft) then // Next Point
 begin
  DistImgTmp.Canvas.Draw(0,0,DistImage.Picture.Graphic);
  DistImgX:= x;
  DistImgY:= y;
  DistImage.Canvas.MoveTo(DistImgX, DistImgY);
  TotalDist:= TotalDist + Trunc(Ex);
 end;
end;

procedure TMaps.DistImageMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
if DistEnabled then
 begin
  DistImage.Canvas.Draw(0,0,DistImgTmp);
  DistImage.Canvas.MoveTo(DistImgX, DistImgY);
  DistImage.Canvas.LineTo(x,y);
  Ex:= (X-DistImgX) * Escala;
  Ex2:= (Y-DistImgY) * Escala;
  Ex:= sqrt(Ex*Ex+Ex2*Ex2);
  Label52.Caption:= Format('%f km.',[TotalDist + Ex]);
  Label52.Repaint;
 end;
end;
0
Comment
Question by:menorcanet
6 Comments
 
LVL 8

Expert Comment

by:TOndrej
Comment Utility
You're drawing the whole image on every mousemove... <shudder>
How about leaving the image as is, and using a xor pen to draw the line? (first time xor draws the line, second time it erases)
0
 

Author Comment

by:menorcanet
Comment Utility
umm, its the first time I'm using the canvas drawing
functions, brushes etc, don't know very well how to
do it properly, could you drop some code ? I can add
more points if needed.

Thanks for your time.
0
 

Expert Comment

by:DirkVerdonck
Comment Utility
Redrawing the complete bitmap every time is going to cost a lot in performance.  I don't think you're ever gonna make it work acceptably on a standard machine.

What I would try is the following:  have two canvasses, one with the image in it, and one of exactly the same size directly above it, and set to be transparant.  So when you move the mouse, you don't redraw the bitmap, just clear the upper canvas and draw the line again.

Hope this helps...
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 8

Accepted Solution

by:
TOndrej earned 100 total points
Comment Utility
Just a very quick demo, Image1.Visible is False.

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure Form1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure Form1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
    procedure Form1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure FormCreate(Sender: TObject);
    procedure FormPaint(Sender: TObject);
  private
    FLine: array[0..1] of TPoint;
    procedure DrawLine;
  public
  end;

procedure TForm1.DrawLine;
begin
  with Canvas do
  begin
    Pen.Color := clWhite;
    Pen.Mode := pmXor;
    with FLine[0] do
      MoveTo(X, Y);
    with FLine[1] do
      LineTo(X, Y);
  end;
end;

procedure TForm1.Form1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  FLine[0] := Point(X, Y);
end;

procedure TForm1.Form1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  if FLine[0].X <> -1 then
  begin
    if FLine[1].X <> -1 then // erase previous line
      DrawLine;
    FLine[1] := Point(X, Y);
    DrawLine; // draw new line
  end;
end;

procedure TForm1.Form1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  DrawLine; // erase previous line
  FLine[0] := Point(-1, -1);
  FLine[1] := Point(-1, -1);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FLine[0] := Point(-1, -1);
  FLine[1] := Point(-1, -1);
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
  Canvas.Draw(0, 0, Image1.Picture.Graphic);
end;
0
 

Author Comment

by:menorcanet
Comment Utility
Hello, thanks again. I tried the code and it works nicely!
I will learn from it an adapt it to my current code; I
will make a canvas and jpeg (would it be worth the speed
using a bitmap in stead of jpeg?) in memory.

brb
0
 

Expert Comment

by:S_Warrior
Comment Utility
Try to draw the line's on the onPaint event.
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now