Recent

Author Topic: [SOLVED] How to move an image?  (Read 6321 times)

avv210

  • New Member
  • *
  • Posts: 13
[SOLVED] How to move an image?
« on: December 15, 2021, 02:38:55 pm »
Hello folks, I am new to this forum. I have Digital Image Processing Course in my college. So I make a GUI Software for my assignment.
I use TEdit as an input box (for X axis and Y axis). Then I want to process the input to make my image move to the coordinated value.

As an example, I have an image size 100x177. Then I want to move the image to coordinated location, X = 10 and Y = 28.
The translation formula is:
x' = Tx + x --> for X coordinate
y' = Ty + y --> for Y coordinate
where, x' and y' is the new coordinate, Tx and Ty is an input value, x and y is the original coordinate.

How can I achieve that?

Source code: https://pastebin.com/xExgPZNX

*Note: I apologize that I can't attach the project, because the file is too big for the forum to load.
« Last Edit: December 20, 2021, 11:49:56 am by avv210 »

wp

  • Hero Member
  • *****
  • Posts: 9606
Welcome here.

It's your first post, so you are excused. But I would urge you to post code not on some cloud server somewhere in the internet where it will soon be gone making your post worthless for all future readers of your post. It would be much better if you'd pack .pas, .lfm, .lpr and .lpi files (and maybe the image file if it is loaded at runtime) into a single zip which you can upload here under "Attachments and other options". This way your project will always be attached to your post, and - very important - everybody can compile and test your project and can easily propose improvements, help with bugs etc. This is much easier with the help of the compiler than just by reading your code (which is even only half of the story because the property values stored in the lfm file are not available).

The first question that I have is: Your code shows that you have a TImage component of the form. Do you want to move the image as a whole, i.e. keep the image contents unchanged and reposition the image relative to its container, the form? Or do you want to move some part of the image contents relative to the rest of the image?
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

Handoko

  • Hero Member
  • *****
  • Posts: 4529
  • My goal: build my own game engine using Lazarus
Hello avv210.
Because you didn't provide the 'full' source code so I cannot test it. A full Lazarus source code should include .lpi, .lpr, .lps files.

Long ago, a fellow asked me to do image zooming and panning for a loaded picture. Luckily I still have the source code. It is tested only on Linux but I think it should work on Windows too. Maybe it can be useful for you:

Code: Pascal  [Select][+][-]
  1. unit Mainform;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   ComCtrls, Buttons, StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     btnOpen: TBitBtn;
  17.     chkCenter: TCheckBox;
  18.     lblYPos: TLabel;
  19.     lblZoom: TLabel;
  20.     lblXPos: TLabel;
  21.     OpenDialog1: TOpenDialog;
  22.     PageControl1: TPageControl;
  23.     PaintBox1: TPaintBox;
  24.     tabImage: TTabSheet;
  25.     tabData: TTabSheet;
  26.     Panel1: TPanel;
  27.     trbYPos: TTrackBar;
  28.     trbZoom: TTrackBar;
  29.     trbXPos: TTrackBar;
  30.     procedure btnOpenClick(Sender: TObject);
  31.     procedure chkCenterChange(Sender: TObject);
  32.     procedure PaintBox1Paint(Sender: TObject);
  33.     procedure PaintBoxUpdate(Sender: TObject);
  34.   private
  35.     { private declarations }
  36.   public
  37.     { public declarations }
  38.   end;
  39.  
  40. var
  41.   Form1: TForm1;
  42.  
  43. implementation
  44.  
  45. {$R *.lfm}
  46.  
  47. var
  48.   LoadedImage: TPicture = nil;
  49.  
  50. { TForm1 }
  51.  
  52. procedure TForm1.btnOpenClick(Sender: TObject);
  53. begin
  54.   if not(OpenDialog1.Execute) then Exit;
  55.  
  56.   if (LoadedImage = nil) then LoadedImage := TPicture.Create;
  57.   LoadedImage.LoadFromFile(OpenDialog1.FileName);
  58.   trbZoom.Position := 100;
  59.   trbXPos.Position := 0;
  60.   trbYPos.Position := 0;
  61.   PaintBox1.Invalidate;
  62. end;
  63.  
  64. procedure TForm1.chkCenterChange(Sender: TObject);
  65. begin
  66.   PaintBox1.Invalidate;
  67. end;
  68.  
  69. procedure TForm1.PaintBox1Paint(Sender: TObject);
  70. var
  71.   ImagePos:  TRect;
  72.   Scale:     Real;
  73.   NewWidth:  Integer;
  74.   NewHeight: Integer;
  75.   X, Y:      Integer;
  76. begin
  77.  
  78.   if not(LoadedImage = nil) then
  79.   begin
  80.     // Calculate zoom and size
  81.     Scale     := PaintBox1.Height / LoadedImage.Height;
  82.     NewHeight := Round(LoadedImage.Height * (trbZoom.Position/100) * Scale);
  83.     NewWidth  := Round(LoadedImage.Width * (trbZoom.Position/100) * Scale);
  84.     // Center image with screen viewport
  85.     X := (PaintBox1.Width-NewWidth) div 2;
  86.     Y := (PaintBox1.Height-NewHeight) div 2;
  87.     // Ofset the image position
  88.     X := X + Round(LoadedImage.Width*trbXPos.Position*Scale) div 100;
  89.     Y := Y + (PaintBox1.Height*trbYPos.Position) div 100;
  90.     // Show it
  91.     ImagePos.Left   := X;
  92.     ImagePos.Right  := ImagePos.Left + NewWidth;
  93.     ImagePos.Top    := Y;
  94.     ImagePos.Bottom := ImagePos.Top + NewHeight;
  95.     PaintBox1.Canvas.StretchDraw(ImagePos, LoadedImage.Graphic);
  96.   end;
  97.  
  98.   // Draw center lines
  99.   if chkCenter.Checked then
  100.     with PaintBox1, PaintBox1.Canvas do
  101.     begin
  102.       X := Width div 2;
  103.       Y := Height div 2;
  104.       Pen.Color := clLime;
  105.       Line(X, 0, X, Height);
  106.       Line(0, Y, Width, Y);
  107.     end;
  108.  
  109. end;
  110.  
  111. procedure TForm1.PaintBoxUpdate(Sender: TObject);
  112. begin
  113.   PaintBox1.Invalidate;
  114. end;
  115.  
  116. end.

wp

  • Hero Member
  • *****
  • Posts: 9606
A full Lazarus source code should include .lpi, .lpr, .lps files.
Sorry, please let me correct and complete this:

The session file (.lps) can be omitted. What must be included, besides .lpr and .lpi, are all .pas and .lfm files, as well as any data files used by the program. Do not include files created by the compiler, such as .ppu, .o, .compiled, or - most of all - .exe because we do not need them for compilation, and because your upload will become too large.

The easiest way to prepare a project for upload to the forum is to call menu "Project" > "Publish project" which creates a zip with all the files required.
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

Handoko

  • Hero Member
  • *****
  • Posts: 4529
  • My goal: build my own game engine using Lazarus
Thank you for the correction.

avv210

  • New Member
  • *
  • Posts: 13
Hello avv210.
Because you didn't provide the 'full' source code so I cannot test it. A full Lazarus source code should include .lpi, .lpr, .lps files.

Long ago, a fellow asked me to do image zooming and panning for a loaded picture. Luckily I still have the source code. It is tested only on Linux but I think it should work on Windows too. Maybe it can be useful for you:

Code: Pascal  [Select][+][-]
  1. unit Mainform;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  9.   ComCtrls, Buttons, StdCtrls;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     btnOpen: TBitBtn;
  17.     chkCenter: TCheckBox;
  18.     lblYPos: TLabel;
  19.     lblZoom: TLabel;
  20.     lblXPos: TLabel;
  21.     OpenDialog1: TOpenDialog;
  22.     PageControl1: TPageControl;
  23.     PaintBox1: TPaintBox;
  24.     tabImage: TTabSheet;
  25.     tabData: TTabSheet;
  26.     Panel1: TPanel;
  27.     trbYPos: TTrackBar;
  28.     trbZoom: TTrackBar;
  29.     trbXPos: TTrackBar;
  30.     procedure btnOpenClick(Sender: TObject);
  31.     procedure chkCenterChange(Sender: TObject);
  32.     procedure PaintBox1Paint(Sender: TObject);
  33.     procedure PaintBoxUpdate(Sender: TObject);
  34.   private
  35.     { private declarations }
  36.   public
  37.     { public declarations }
  38.   end;
  39.  
  40. var
  41.   Form1: TForm1;
  42.  
  43. implementation
  44.  
  45. {$R *.lfm}
  46.  
  47. var
  48.   LoadedImage: TPicture = nil;
  49.  
  50. { TForm1 }
  51.  
  52. procedure TForm1.btnOpenClick(Sender: TObject);
  53. begin
  54.   if not(OpenDialog1.Execute) then Exit;
  55.  
  56.   if (LoadedImage = nil) then LoadedImage := TPicture.Create;
  57.   LoadedImage.LoadFromFile(OpenDialog1.FileName);
  58.   trbZoom.Position := 100;
  59.   trbXPos.Position := 0;
  60.   trbYPos.Position := 0;
  61.   PaintBox1.Invalidate;
  62. end;
  63.  
  64. procedure TForm1.chkCenterChange(Sender: TObject);
  65. begin
  66.   PaintBox1.Invalidate;
  67. end;
  68.  
  69. procedure TForm1.PaintBox1Paint(Sender: TObject);
  70. var
  71.   ImagePos:  TRect;
  72.   Scale:     Real;
  73.   NewWidth:  Integer;
  74.   NewHeight: Integer;
  75.   X, Y:      Integer;
  76. begin
  77.  
  78.   if not(LoadedImage = nil) then
  79.   begin
  80.     // Calculate zoom and size
  81.     Scale     := PaintBox1.Height / LoadedImage.Height;
  82.     NewHeight := Round(LoadedImage.Height * (trbZoom.Position/100) * Scale);
  83.     NewWidth  := Round(LoadedImage.Width * (trbZoom.Position/100) * Scale);
  84.     // Center image with screen viewport
  85.     X := (PaintBox1.Width-NewWidth) div 2;
  86.     Y := (PaintBox1.Height-NewHeight) div 2;
  87.     // Ofset the image position
  88.     X := X + Round(LoadedImage.Width*trbXPos.Position*Scale) div 100;
  89.     Y := Y + (PaintBox1.Height*trbYPos.Position) div 100;
  90.     // Show it
  91.     ImagePos.Left   := X;
  92.     ImagePos.Right  := ImagePos.Left + NewWidth;
  93.     ImagePos.Top    := Y;
  94.     ImagePos.Bottom := ImagePos.Top + NewHeight;
  95.     PaintBox1.Canvas.StretchDraw(ImagePos, LoadedImage.Graphic);
  96.   end;
  97.  
  98.   // Draw center lines
  99.   if chkCenter.Checked then
  100.     with PaintBox1, PaintBox1.Canvas do
  101.     begin
  102.       X := Width div 2;
  103.       Y := Height div 2;
  104.       Pen.Color := clLime;
  105.       Line(X, 0, X, Height);
  106.       Line(0, Y, Width, Y);
  107.     end;
  108.  
  109. end;
  110.  
  111. procedure TForm1.PaintBoxUpdate(Sender: TObject);
  112. begin
  113.   PaintBox1.Invalidate;
  114. end;
  115.  
  116. end.

Hey! Uh..I am bit confuse to use your component, I try to recreate and understand your project. But I am so confused. Can you help me for an explanatory. It'll be helpful. Thank you by the way.

Handoko

  • Hero Member
  • *****
  • Posts: 4529
  • My goal: build my own game engine using Lazarus
These are the main things in the example:
1. TPaintBox
2. TTrackBar
3. TOpenDialog

TOpenDialog


It is used to let user to select a file. To use it, you call its Execute method, see line #54.

After user select a file, we load and store the image into LoadedImage, see line #56 and #57. And we set the default values for Zoom, X and Y, see lines #58..#60. The line #61 is needed because calling PaintBox.Invalidate will let the painbox to refresh its image.

TTrackbar

TTrackbar is used to let users to provide a value by using arrow keys and mouse.

There are 3 trackbars used in the example, see lines #27..29. The starting values of those trackbars were set on the lines #58..60.

When user modify any value of the trackbars, line #33 PaintBoxUpdate will be called because it was set in their OnChange event. The PaintBoxUpdate simply calls Invalidate, see line #113.

TPainBox

TPainBox is used for showing and modifying image on the screen. Usually we do it by accessing its canvas. In this case we use Canvas.StretchDraw, see line #95.

OnPaint event is where you should put the code for showing the image, see line #69. Some calculations needed be done before really showing the image. First we calculate the size based on the zoom trackbar, see line #80. Line #85..86 are for centering the image, first the X then Y. And the calculate the offset, see line #87. After all the needed values have been calculated, now see show the image on the painbox, see line #90.

Handoko

  • Hero Member
  • *****
  • Posts: 4529
  • My goal: build my own game engine using Lazarus
If you have problem understanding the previous example, try this. This one is simpler.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Dialogs, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Image1: TImage;
  16.     btnLoad: TButton;
  17.     btnMove: TButton;
  18.     procedure btnMoveClick(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure btnLoadClick(Sender: TObject);
  21.   private
  22.     procedure ShowPosition;
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.btnLoadClick(Sender: TObject);
  35. begin
  36.  
  37.   // Load the image
  38.   try
  39.     Image1.Picture.LoadFromFile('project1.ico');
  40.   except
  41.     Halt; // Quit the program if fails to load the image
  42.   end;
  43.  
  44.   // Set the image position
  45.   Image1.Left := 50; // X
  46.   Image1.Top  := 50; // Y
  47.   ShowPosition;
  48.  
  49.   // Notify the user
  50.   ShowMessage('Image loaded.');
  51.  
  52.   // Set the buttons
  53.   btnLoad.Enabled := False;
  54.   btnMove.Enabled := True;
  55.  
  56. end;
  57.  
  58. procedure TForm1.ShowPosition;
  59. begin
  60.   Caption := 'X=' + Image1.Left.ToString + ' | Y=' + Image1.Top.ToString;
  61. end;
  62.  
  63. procedure TForm1.FormCreate(Sender: TObject);
  64. begin
  65.   // Disable btnMove
  66.   btnMove.Enabled := False;
  67. end;
  68.  
  69. procedure TForm1.btnMoveClick(Sender: TObject);
  70. var
  71.   strX, strY: string;
  72.   X, Y:       Integer;
  73. begin
  74.  
  75.   // User input
  76.   if not(InputQuery('Move the image', 'X shift =', strX)) then Exit;
  77.   if not(InputQuery('Move the image', 'Y shift =', strY)) then Exit;
  78.  
  79.   // Validation
  80.   if not(TryStrToInt(strX, X)) then
  81.   begin
  82.     ShowMessage('Invalid value for X.');
  83.     Exit;
  84.   end;
  85.   if not(TryStrToInt(strY, Y)) then
  86.   begin
  87.     ShowMessage('Invalid value for Y.');
  88.     Exit;
  89.   end;
  90.   if (X < -100) or (X > 100) then
  91.   begin
  92.     ShowMessage('-100 <= X <= 100.');
  93.     Exit;
  94.   end;
  95.   if (Y < -100) or (Y > 100) then
  96.   begin
  97.     ShowMessage('-100 <= Y <= 100.');
  98.     Exit;
  99.   end;
  100.  
  101.   // Move the image
  102.   Image1.Left := Image1.Left + X;
  103.   Image1.Top  := Image1.Top  + Y;
  104.   ShowPosition;
  105.  
  106. end;
  107.  
  108. end.

avv210

  • New Member
  • *
  • Posts: 13
If you have problem understanding the previous example, try this. This one is simpler.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Dialogs, StdCtrls, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Image1: TImage;
  16.     btnLoad: TButton;
  17.     btnMove: TButton;
  18.     procedure btnMoveClick(Sender: TObject);
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure btnLoadClick(Sender: TObject);
  21.   private
  22.     procedure ShowPosition;
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.btnLoadClick(Sender: TObject);
  35. begin
  36.  
  37.   // Load the image
  38.   try
  39.     Image1.Picture.LoadFromFile('project1.ico');
  40.   except
  41.     Halt; // Quit the program if fails to load the image
  42.   end;
  43.  
  44.   // Set the image position
  45.   Image1.Left := 50; // X
  46.   Image1.Top  := 50; // Y
  47.   ShowPosition;
  48.  
  49.   // Notify the user
  50.   ShowMessage('Image loaded.');
  51.  
  52.   // Set the buttons
  53.   btnLoad.Enabled := False;
  54.   btnMove.Enabled := True;
  55.  
  56. end;
  57.  
  58. procedure TForm1.ShowPosition;
  59. begin
  60.   Caption := 'X=' + Image1.Left.ToString + ' | Y=' + Image1.Top.ToString;
  61. end;
  62.  
  63. procedure TForm1.FormCreate(Sender: TObject);
  64. begin
  65.   // Disable btnMove
  66.   btnMove.Enabled := False;
  67. end;
  68.  
  69. procedure TForm1.btnMoveClick(Sender: TObject);
  70. var
  71.   strX, strY: string;
  72.   X, Y:       Integer;
  73. begin
  74.  
  75.   // User input
  76.   if not(InputQuery('Move the image', 'X shift =', strX)) then Exit;
  77.   if not(InputQuery('Move the image', 'Y shift =', strY)) then Exit;
  78.  
  79.   // Validation
  80.   if not(TryStrToInt(strX, X)) then
  81.   begin
  82.     ShowMessage('Invalid value for X.');
  83.     Exit;
  84.   end;
  85.   if not(TryStrToInt(strY, Y)) then
  86.   begin
  87.     ShowMessage('Invalid value for Y.');
  88.     Exit;
  89.   end;
  90.   if (X < -100) or (X > 100) then
  91.   begin
  92.     ShowMessage('-100 <= X <= 100.');
  93.     Exit;
  94.   end;
  95.   if (Y < -100) or (Y > 100) then
  96.   begin
  97.     ShowMessage('-100 <= Y <= 100.');
  98.     Exit;
  99.   end;
  100.  
  101.   // Move the image
  102.   Image1.Left := Image1.Left + X;
  103.   Image1.Top  := Image1.Top  + Y;
  104.   ShowPosition;
  105.  
  106. end;
  107.  
  108. end.

Thank you :)

 

TinyPortal © 2005-2018