Solved

Canvas.LineTo on TImage very SLOW

Posted on 2002-06-27
6
608 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
Independent Software Vendors: 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

Secure Your Active Directory - April 20, 2017

Active Directory plays a critical role in your company’s IT infrastructure and keeping it secure in today’s hacker-infested world is a must.
Microsoft published 300+ pages of guidance, but who has the time, money, and resources to implement? Register now to find an easier way.

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 The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …
How to Install VMware Tools in Red Hat Enterprise Linux 6.4 (RHEL 6.4) Step-by-Step Tutorial

730 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