Solved

Canvas.LineTo on TImage very SLOW

Posted on 2002-06-27
6
620 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
6 Comments
 
LVL 8

Expert Comment

by:TOndrej
ID: 7113035
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
ID: 7113054
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
ID: 7113065
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 8

Accepted Solution

by:
TOndrej earned 100 total points
ID: 7113110
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
ID: 7114352
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
ID: 7230252
Try to draw the line's on the onPaint event.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In this video, viewers are given an introduction to using the Windows 10 Snipping Tool, how to quickly locate it when it's needed and also how make it always available with a single click of a mouse button, by pinning it to the Desktop Task Bar. Int…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…

687 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