?
Solved

Canvas.LineTo on TImage very SLOW

Posted on 2002-06-27
6
Medium Priority
?
629 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 8

Accepted Solution

by:
TOndrej earned 400 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

Want to be a Web Developer? Get Certified Today!

Enroll in the Certified Web Development Professional course package to learn HTML, Javascript, and PHP. Build a solid foundation to work toward your dream job!

Question has a verified solution.

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

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…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses

800 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