ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Problem with croptool scaling btwn imageenview's
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

AdrianKnowles

USA
35 Posts

Posted - Sep 14 2017 :  02:28:33  Show Profile  Reply
Hi,
I have some code that is meant to display an ROI on 3 different imageenviews. Some coordinate values are shared between the 3 ROIs.

The code below works as intended when I don't load any images.
However once I load images then the ROI's become scaled incorrectly.

It seems that the 'shared' coordinates no longer work and the ROI's become scaled incorrectly.

Am I doing anything silly here??



unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, hyieutils, iexBitmaps, hyiedefs,
  iesettings, iexLayers, iexRulers, Vcl.StdCtrls, ieview, imageenview, imageen,
  ieopensavedlg;

type
  TForm1 = class(TForm)
    ImageEnview1: TImageEn;
    ImageEnview2: TImageEn;
    ImageEnview3: TImageEn;
    Button1: TButton;
    Load1: TButton;
    Load2: TButton;
    Load3: TButton;
    OpenImageEnDialog1: TOpenImageEnDialog;
    procedure Button1Click(Sender: TObject);
    procedure ImageEnview1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);

    procedure Load1Click(Sender: TObject);
    procedure Load2Click(Sender: TObject);
    procedure Load3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  x1,y1, x2,y2,x3,y3,x4,y4: integer;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
var
  arect: TRect;
begin
  ImageEnView1.MouseInteract := [miCropTool];
  ImageEnView2.MouseInteract := [miCropTool];
  ImageEnView3.MouseInteract := [miCropTool];
// Disable guide lines (on image thirds)
  ImageEnView1.CropToolInteraction.DrawGuides := False;
  ImageEnView2.CropToolInteraction.DrawGuides := False;
  ImageEnView3.CropToolInteraction.DrawGuides := False;
// Make larger grips
  ImageEnView1.CropToolInteraction.GripSize := 14;  //20
  ImageEnView2.CropToolInteraction.GripSize := 14;
  ImageEnView3.CropToolInteraction.GripSize := 14;

  x1:= 100;
  y1:= 100;
  x2:= 200;
  y2:= 100;
  x3:= 200;
  y3:= 200;
  x4:= 100;
  y4:= 200;


   ImageEnView1.SelectionBase :=  iesbBitmap;
      ImageEnView2.SelectionBase :=  iesbBitmap;
      ImageEnView3.SelectionBase :=  iesbBitmap;



  ARect := Rect(x1,y1,x3,y3);
  ImageEnView1.CropToolInteraction.SetBitmapPolygon( ARect );
  ImageEnView1.Invalidate();
  ARect := Rect(x1,y1,x3,y3);
  ImageEnView2.CropToolInteraction.SetBitmapPolygon( ARect );
  ImageEnView2.Invalidate();
  ARect := Rect(x1,y1,x3,y3);
  ImageEnView3.CropToolInteraction.SetBitmapPolygon( ARect );
  ImageEnView3.Invalidate();

end;






procedure TForm1.ImageEnview1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  arect: TRect;
  CopyRect: Trect;
  View1X1,View1Y1, View1X2,View1Y2: integer;
  View2X1,View2Y1, View2X2,View2Y2,View2X3,View2Y3 : integer;
    View3X1,View3Y1, View3X2,View3Y2,View3X3,View3Y3 : integer;
 // x1,y1, x2,y2,x3,y3,x4,y4: integer;
begin
  //ImageEnView1.CropToolInteraction.Crop();
    //Added below 3 lines//
  if (ssLeft in shift) then
  begin
    //  Item 0 is Top-Left, item 1 is Top-Right, item 2 is Bottom-Right and item 3 is Bottom-Left



      ImageEnView1.SelectionBase :=  iesbBitmap;
      ImageEnView2.SelectionBase :=  iesbBitmap;
      ImageEnView3.SelectionBase :=  iesbBitmap;



    X1:= Round(imageenview1.CropToolInteraction.RotatedPolygon[0].X );
    Y1:= Round(imageenview1.CropToolInteraction.RotatedPolygon[0].y );
    X2:= Round(imageenview1.CropToolInteraction.RotatedPolygon[1].x );
    Y2:= Round(imageenview1.CropToolInteraction.RotatedPolygon[1].y );
    X3:= Round(imageenview1.CropToolInteraction.RotatedPolygon[2].x );
    Y3:= Round(imageenview1.CropToolInteraction.RotatedPolygon[2].y );
    X4:= Round(imageenview1.CropToolInteraction.RotatedPolygon[3].x );
    Y4:= Round(imageenview1.CropToolInteraction.RotatedPolygon[3].y );

    View2X1:= Round(imageenview2.CropToolInteraction.RotatedPolygon[0].x );
    View2Y1:= Round(imageenview2.CropToolInteraction.RotatedPolygon[0].y );
    View2X3:= Round(imageenview2.CropToolInteraction.RotatedPolygon[2].x );
    View2Y3:= Round(imageenview2.CropToolInteraction.RotatedPolygon[2].y );

    View3X1:= Round(imageenview3.CropToolInteraction.RotatedPolygon[0].x );
    View3Y1:= Round(imageenview3.CropToolInteraction.RotatedPolygon[0].y );
    View3X3:= Round(imageenview3.CropToolInteraction.RotatedPolygon[2].x );
    View3Y3:= Round(imageenview3.CropToolInteraction.RotatedPolygon[2].y );

    ARect := Rect(View2X1,Y1,View2X3,Y3) ;
    ImageEnView2.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView2.Invalidate();

    ARect := Rect(x1,View3Y1,x3,View3Y3);
    ImageEnView3.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView3.Invalidate();

  end;



end;

procedure TForm1.Load1Click(Sender: TObject);
var
  fn:string;
  tags : TIEDicomTags;
begin
  OpenImageEnDialog1.AutoSetFilterFileType := ioDicom;
  if OpenImageEnDialog1.Execute then
  begin
    fn := OpenImageEnDialog1.FileName;

    imageenview1.IO.LoadFromFile(fn);
    ImageEnView1.Fit;

  end;
end;

procedure TForm1.Load2Click(Sender: TObject);
var
  fn:string;
  tags : TIEDicomTags;
begin
  OpenImageEnDialog1.AutoSetFilterFileType := ioDicom;
  if OpenImageEnDialog1.Execute then
  begin
    fn := OpenImageEnDialog1.FileName;

    imageenview2.IO.LoadFromFile(fn);

    ImageEnView2.Fit;

  end;
end;
procedure TForm1.Load3Click(Sender: TObject);
var
  fn:string;
  tags : TIEDicomTags;
begin
  OpenImageEnDialog1.AutoSetFilterFileType := ioDicom;
  if OpenImageEnDialog1.Execute then
  begin
    fn := OpenImageEnDialog1.FileName;

    imageenview3.IO.LoadFromFile(fn);


    ImageEnView3.Fit;


  end;
end;

end.

xequte

38182 Posts

Posted - Sep 14 2017 :  22:42:12  Show Profile  Reply
Hi

Before I debug this, your demo does not align even without images, is that intended?



Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

AdrianKnowles

USA
35 Posts

Posted - Sep 15 2017 :  02:06:58  Show Profile  Reply
HI,
I've attached an image showing the expected behaviour (empty viewer) and the changed behaviour once you have loaded images into each viewer

Go to Top of Page

xequte

38182 Posts

Posted - Sep 17 2017 :  19:17:27  Show Profile  Reply

Hi

RotatedPolygon values are specified in terms of the bitmap, so if the bitmaps are different sizes, then you will need to scale your x and y values appropriately, e.g. as a percentage of width or height, or in terms of screen (using TImageEnView.XBmp2Scr and TImageEnView.YBmp2Scr).

For example, here is your code that converts the bitmap values to screen values:


procedure TForm1.ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  arect: TRect;
  CopyRect: Trect;
  View1X1,View1Y1, View1X2,View1Y2: integer;
  View2X1,View2Y1, View2X2,View2Y2,View2X3,View2Y3 : integer;
    View3X1,View3Y1, View3X2,View3Y2,View3X3,View3Y3 : integer;
begin
  if (ssLeft in shift) then
  begin
    //  Item 0 is Top-Left, item 1 is Top-Right, item 2 is Bottom-Right and item 3 is Bottom-Left

    X1:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].X ));
    Y1:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].y ));
    X2:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].x ));
    Y2:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].y ));
    X3:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].x ));
    Y3:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].y ));
    X4:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].x ));
    Y4:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].y ));

    View2X1:= Imageenview2.XScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[0].x ));
    View2Y1:= Imageenview2.YScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[0].y ));
    View2X3:= Imageenview2.XScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[2].x ));
    View2Y3:= Imageenview2.YScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[2].y ));

    View3X1:= Imageenview3.XScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[0].x ));
    View3Y1:= Imageenview3.YScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[0].y ));
    View3X3:= Imageenview3.XScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[2].x ));
    View3Y3:= Imageenview3.YScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[2].y ));

    ARect := Rect(View2X1,View2Y1,View2X3,View2Y3) ;
    ImageEnView2.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView2.Invalidate();

    ARect := Rect(View3X1,View3Y1,View3X3,View3Y3);
    ImageEnView3.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView3.Invalidate();
  end;
end;


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

AdrianKnowles

USA
35 Posts

Posted - Sep 19 2017 :  10:57:57  Show Profile  Reply
Hi Nigel,
Many thanks for the assistance. Its still not working as intended although better.


As you can see from the video I posted to your email today when no image is loaded the ROI’s across the imageenviews work as intended. Once I load images (identical resolutions/formats etc...) then you see some scaling occurs.





procedure TForm1.ImageEnview1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  arect: TRect;
  CopyRect: Trect;
  View1X1,View1Y1, View1X2,View1Y2: integer;
  View2X1,View2Y1, View2X2,View2Y2,View2X3,View2Y3 : integer;
  View3X1,View3Y1, View3X2,View3Y2,View3X3,View3Y3 : integer;
begin
  if (ssLeft in shift) then
  begin
    //  Item 0 is Top-Left, item 1 is Top-Right, item 2 is Bottom-Right and item 3 is Bottom-Left


    X1:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].X ));
    Y1:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].y ));
    X2:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].x ));
    Y2:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].y ));
    X3:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].x ));
    Y3:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].y ));
    X4:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].x ));
    Y4:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].y ));

    View2X1:= Imageenview2.XScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[0].x ));
    View2Y1:= Imageenview2.YScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[0].y ));
    View2X3:= Imageenview2.xScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[2].x ));
    View2Y3:= Imageenview2.YScr2Bmp( Round(imageenview2.CropToolInteraction.RotatedPolygon[2].y ));

    View3X1:= Imageenview3.XScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[0].x ));
    View3Y1:= Imageenview3.YScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[0].y ));
    View3X3:= Imageenview3.XScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[2].x ));
    View3Y3:= Imageenview3.YScr2Bmp( Round(imageenview3.CropToolInteraction.RotatedPolygon[2].y ));


    ARect := Rect(View2X1,Y1,View2X3,Y3) ;
    ImageEnView2.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView2.Invalidate();

    ARect := Rect(x1,View3Y1,x3,View3Y3);
    ImageEnView3.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView3.Invalidate();

  end;
end;





Kind regards,
Adrian






attach/AdrianKnowles/2017919105653_19 Sept.zip
3091.56 KB
Go to Top of Page

AdrianKnowles

USA
35 Posts

Posted - Sep 19 2017 :  11:00:06  Show Profile  Reply
I attached a .zip file to my previous pitch which contains the movie.

Thank you.
Go to Top of Page

xequte

38182 Posts

Posted - Sep 19 2017 :  17:46:13  Show Profile  Reply
Hi Adrian

I'm not seeing that.



Please attach a zip of your test project and the three source images.



Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page

AdrianKnowles

USA
35 Posts

Posted - Sep 20 2017 :  10:08:39  Show Profile  Reply
Hi,
here you go

Kind regards,
Adrian

attach/AdrianKnowles/201792010819_Unit1.zip
104.55 KB
Go to Top of Page

xequte

38182 Posts

Posted - Sep 20 2017 :  17:53:09  Show Profile  Reply
OK, I'm not 100% clear on what the code is supposed to do here, but the big issue you are going to encounter is rounding errors. RotatedPolygon are double values so the frequent rounding while moving the mouse will change their values.

To counter that, I added some private values:

    fView2X1: Double;
    fView2X3: Double;
    fView2Y3: Double;
    fView3Y1: Double;
    fView3Y3: Double;


Which you need to reset before using, or if the user manually changes that selection:

  fView2X1 := -99;
  fView2X3 := -99;
  fView2Y3 := -99;

  fView3Y1 := -99;
  fView3Y3 := -99;



This is the code I used:

procedure TForm1.ImageEnview1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  arect: TRect;
  CopyRect: Trect;
  x1,y1, x2,y2,x3,y3,x4,y4: integer;
  View1X1,View1Y1, View1X2,View1Y2: integer;
  View2Y1: Integer;
  View3X1,View3X3 : integer;
begin
  if (ssLeft in shift) then
  begin
    //  Item 0 is Top-Left, item 1 is Top-Right, item 2 is Bottom-Right and item 3 is Bottom-Left

    X1:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].X ));
    Y1:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[0].y ));
    X2:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].x ));
    Y2:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[1].y ));
    X3:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].x ));
    Y3:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[2].y ));
    X4:= imageenview1.XBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].x ));
    Y4:= imageenview1.YBmp2Scr( Round(imageenview1.CropToolInteraction.RotatedPolygon[3].y ));

    // Only share y coord from point 0
    if fView2X1 = -99 then
      fView2X1:= Imageenview2.CropToolInteraction.RotatedPolygon[0].X;
    View2Y1:= Imageenview2.YScr2Bmp( Y1 );
    if fView2X3 = -99 then
      fView2X3:= Round( Imageenview2.CropToolInteraction.RotatedPolygon[2].X );
    if fView2Y3 = -99 then
      fView2Y3:= Round( Imageenview2.CropToolInteraction.RotatedPolygon[2].Y );

    // X coords from point 0 and 3 are shared
    View3X1:= Imageenview3.XScr2Bmp( X1 );
    if fView3Y1 = -99 then
      fView3Y1:= Imageenview3.CropToolInteraction.RotatedPolygon[0].Y;
    View3X3 := Imageenview3.XScr2Bmp( X3 );
    if fView3Y3 = -99 then
      fView3Y3:= Imageenview3.CropToolInteraction.RotatedPolygon[2].Y;


    OneX     .Text := IntToStr( X1 );
    OneY     .Text := IntToStr( Y1 );
    ThreeX   .Text := IntToStr( X3 );
    THreeY   .Text := IntToStr( Y3 );

    TwoX     .Text := IntToStr( Round( fView2X1 ));
    TwoY     .Text := IntToStr( Round( View2Y1 ));
    FourX    .Text := IntToStr( Round( fView2X3 ));
    FourY    .Text := IntToStr( Round( fView2Y3 ));

    thirdx1  .Text := IntToStr( Round( View3X1 ));
    thirdy1  .Text := IntToStr( Round( fView3Y1 ));
    thirdx3  .Text := IntToStr( Round( View3X3 ));
    thirdy3  .Text := IntToStr( Round( fView3Y3 ));


    ARect := Rect( Round( fView2X1 ), Round( View2Y1 ), Round( fView2X3 ), Round( fView2Y3 )) ;
    ImageEnView2.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView2.Invalidate();

    ARect := Rect( Round( View3X1 ), Round( fView3Y1 ), Round( View3X3 ), Round( fView3Y3 ));
    ImageEnView3.CropToolInteraction.SetBitmapPolygon( ARect );
    ImageEnView3.Invalidate();
  end;
end;


Nigel
Xequte Software
www.xequte.com
nigel@xequte.com
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: