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

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Coordinates

Note: You must be registered in order to post a reply.
To register, click here. Registration is FREE!

View 
UserName:
Password:
Format  Bold Italicized Underline  Align Left Centered Align Right  Horizontal Rule  Insert Hyperlink   Browse for an image to attach to your post Browse for a zip to attach to your post Insert Code  Insert Quote Insert List
   
Message 

 

Emoji
Smile [:)] Big Smile [:D] Cool [8D] Blush [:I]
Tongue [:P] Evil [):] Wink [;)] Black Eye [B)]
Frown [:(] Shocked [:0] Angry [:(!] Sleepy [|)]
Kisses [:X] Approve [^] Disapprove [V] Question [?]

 
Check here to subscribe to this topic.
   

T O P I C    R E V I E W
jwhite Posted - Aug 04 2015 : 08:12:07
Is there functionality in the TImageEnMView similar to TImageEnView.XScr2Bmp?

I have the drawing working on the TImageEnMView but the coordinates are
off depending where I am scrolled to. If I have not scrolled the line are in the correct position. If I have scrolled the lines are higher (Y coordinate) where the cursor is.

Thank.

5   L A T E S T    R E P L I E S    (Newest First)
w2m Posted - Aug 13 2015 : 10:07:46
There is no need to use TImageEnMView for drawing to accomplish what you are looking for. You can do it all with TImageEnView by using layers. Each frame in the tif file appears as a layer with a vertical scrolling layout, meaning each frame is drawn below the previous frame. The component scrolls with the scrollbar or with touch gesture and each frame can be painted on with a brush.

The only thing required is that the layer is clicked on one time before drawing to select the frame so the drawing coordinates are correct for the selected layer.

A demo can be found here:
attach/w2m/201581395427_ImageEnViewLayerDraw.zip
106.62 KB

I tried attaching a small video but the system will not accept mp4 files, so you will have to compile and run it to see how it functions.

Here is the source:
unit Unit1;

interface

uses
  Windows, Forms, Classes, Controls, Graphics, ieview, iemview, hyiedefs,
  hyieutils, iexBitmaps, imageenio, imageenview, iexHelperFunctions;

type
  TForm1 = class(TForm)
    ImageEnView1: TImageEnView;
    procedure FormShow(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImageEnView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState;
      X, Y: Integer);
    procedure ImageEnView1LayerNotify(Sender: TObject; layer: Integer;
      event: TIELayerEvent);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ImageEnView1.MouseInteract := [];
  ImageEnView1.LayersSync := False;
  ImageEnView1.LayersDrawBox := True;
  { Eliminate the layer grips }
  ImageEnView1.SetLayersGripStyle(0, 0, bsClear, 0, iegsCircle);
  { Eliminate auto cursors }
  ImageEnView1.AutoCursors := False;
end;

procedure TForm1.FormShow(Sender: TObject);
var
  iFrames: Integer;
  i: Integer;
  iLayer: Integer;
  iRatio: Integer;
begin
  WindowState := Forms.wsMaximized;
  iRatio := (Width div ImageEnView1.ClientWidth);
  iFrames := IEGetFileFramesCount('Plain.tif');
  { Resize the base bitmap to the height of all the layers so a scrollbar
    appears }
  ImageEnView1.IEBitmap.IEInitialize(ImageEnView1.ClientWidth,
    ((ImageEnView1.ClientHeight) * iFrames) + ImageEnView1.ClientHeight , clWhite);
  for i := 0 to iFrames do
  begin
      ImageEnView1.IO.Params.ImageIndex := i;
      iLayer := ImageEnView1.LayersCreateFromFile('Plain.tif');
      ImageEnView1.Layers[i].PosX := 0;
      ImageEnView1.Layers[iLayer].PosY := ImageEnView1.Layers[i].Height * i;
      { Lock the layer in place }
      ImageEnView1.Layers[iLayer].Locked := True;
  end;
  ImageEnView1.LayersCurrent := 1;
  ImageEnView1.MouseInteract := [miMoveLayers, miResizeLayers];
  ImageEnView1.Gestures.Pan.Enabled := True;
  ImageEnView1.Zoom := ImageEnView1.Zoom * iRatio;
end;

procedure TForm1.ImageEnView1LayerNotify(Sender: TObject; layer: Integer;
  event: TIELayerEvent);
begin
  { Set the current layer to layer so that when drawing the correct layer
    coordinates are used }
  ImageEnView1.LayersCurrent := layer;
end;

procedure TForm1.ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  iX: Integer;
  iY: Integer;
begin
  ImageEnView1.MouseInteract := [miMoveLayers, miResizeLayers];
  iX := ImageEnView1.Layers[ImageEnView1.LayersCurrent].ConvXScr2Bmp(X);
  iY := ImageEnView1.Layers[ImageEnView1.LayersCurrent].ConvYScr2Bmp(Y);
  { Insure drawing only takes place within the bitmap }
  if (iX >= 0) and (iX <= ImageEnView1.IEBitmap.Width - 1) and (iY >= 0) and
    (iY <= ImageEnView1.IEBitmap.Height - 1) then
  begin
    if ImageEnView1.MouseCapture then
    begin
      ImageEnView1.MouseInteract := [];
      ImageEnView1.IEBitmap.IECanvas.MoveTo(iX, iY);
      ImageEnView1.IEBitmap.IECanvas.Pen.Width := 10;
      ImageEnView1.IEBitmap.IECanvas.Pen.Color := clBlack;
      ImageEnView1.Update;
    end;
  end;
end;

procedure TForm1.ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  iX: Integer;
  iY: Integer;
begin
  ImageEnView1.Update;
  if ImageEnView1.MouseCapture then
  begin
    ImageEnView1.MouseInteract := [];
    iX := ImageEnView1.Layers[ImageEnView1.LayersCurrent].ConvXScr2Bmp(X);
    iY := ImageEnView1.Layers[ImageEnView1.LayersCurrent].ConvYScr2Bmp(Y);
    { Insure drawing only takes place within the bitmap }
    if (iX >= 0) and (iX <= ImageEnView1.IEBitmap.Width - 1) and (iY >= 0) and
      (iY <= ImageEnView1.IEBitmap.Height - 1) then
    begin
      ImageEnView1.IEBitmap.IECanvas.Pen.Width := 10;
      ImageEnView1.IEBitmap.IECanvas.Pen.Color := clBlack;
      ImageEnView1.IEBitmap.IECanvas.LineTo(iX, iY);
      ImageEnView1.Update;
    end;
  end;
end;

procedure TForm1.ImageEnView1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  { If you do not do this then the OnLayerNotify Event does not execute so the
    active or current layer index can not be obtained in the
    ImageEnView1LayerNotify event }
  ImageEnView1.MouseInteract := [miMoveLayers, miResizeLayers];
end;

end.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
jwhite Posted - Aug 12 2015 : 15:41:45
Thanks for your response Bill.

I was pretty sure that the TImageEnMView was not necessarily designed for canvas drawing but I figured out a way to make it work (almost). The reason I need to use the TImageEnMView is that I want to show all pages like a report (I have the thumbnails enlarged for this) instead of having to select a thumbnail, then draw, repeat (TImageEnView). This is going to be on a tablet so I am wanting the report feel so that user can scroll to next page, sign, scroll to next page, sign, etc. The program generates as a PDF then I convert it to a multi-page tiff.

I tried the predominate PDF components, but they do not allow you to draw and view the drawing at the same time (based on their support). You can draw, save, reload, and it will work but that's not ideal for interactivity (user cannot see their signature as they sign it).

I thought about reproducing the TImageEnView.XScr2Bmp (which works well) functionality and came to the same conclusion as you did. We could do it but then it can become an update nightmare. I was hoping someone else had come across the solution I am looking for.

Ideally TImageEnMView will be updated to have the same functionality as TImageEnView regarding canvas drawing. :)

w2m Posted - Aug 12 2015 : 14:45:59
I do not think the ImageEn developed TImageEnMView to allow canvas drawing. I suspect the problem is the coordinates are client biased and not bitmap biased, so you have to convert the client coordinates to bitmap coordinates in order to get the drawing to align with the cursor position.

Having said that, you will have to develop your own conversion similar to TImageEnView.XScr2Bmp (X) and TImageEnView.YScr2Bmp (Y); I looked at the methods, but found it would take awhile to develop a stand-a-lone conversion that could be used with TImageEnMView.

What I do not understand is why are you using TImageEnMView to begin with rather than TImageEnView?
I would change your code to use TImageEnView for drawing and use TImageEnMView to store thumbnails of the tiff frames. So when you select a frame in TImageEnMView the full frame image is loaded into TImageEnView for drawing.

That way you will have access to the client to bitmap conversion functions already built into TImageEnView.

TImageEnView.XScr2Bmp

Declaration
function XScr2Bmp(x: integer): integer;

Description
The XScr2Bmp and YScr2Bmp methods convert a window coordinate to the corresponding bitmap coordinate (considering Zoom and ViewX, ViewY status).

x is a window coordinate.
Returns a bitmap coordinate which can be negative or larger than bitmap size if the window coordinate is beyond the displayed image's boundaries.

Example
// X and Y are MOUSE coordinates
bx := ImageEnView1.XScr2Bmp(X);
by := ImageEnView1.YScr2Bmp(Y);
// now bx and by are Bitmap coordinates (referred to the ImageEnView1.Bitmap)

An alternative approach would be to create a layer for each tiff frame aligned vertically similar to your TImageEnMView demo, but use TImageEnView for the component. That way you could have a vertically scrollable TImageEnView with a layer for each frame with access to client layer to bitmap coordinate conversion methods of TImageEnView:

TIELayer.ConvXScr2Bmp

Declaration
function ConvXScr2Bmp(x: Integer): Integer;

Description
Converts screen coordinates to bitmap coordinates, with consideration to the layer position and size.

Bill Miller
Adirondack Software & Graphics
Email: w2m@hughes.net
EBook: http://www.imageen.com/ebook/
Custom Commercial ImageEn Development
jwhite Posted - Aug 12 2015 : 13:26:03
Below is the code I am using. I have a 5 page tif that I am loading. I can draw on each page (hold down left mouse button and move mouse) but the lines drawn are not exactly below the cursor. The project is attached.


unit Unit1;

interface

uses
  Windows, Forms, Classes, Controls, Graphics, ieview, iemview;

type
  TForm1 = class(TForm)
    ImageEnView1: TImageEnMView;
    procedure FormShow(Sender: TObject);
    procedure ImageEnView1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure ImageEnView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImageEnView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImageEnView1ImageAtPos(Sender: TObject; var idx: Integer; x,
      y: Integer);
  private
    { Private declarations }
    Drawing: Boolean;
    Ratio: Double;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
begin
  WindowState := Forms.wsMaximized;

  Ratio := (Width / ImageEnView1.ThumbWidth);

  ImageEnView1.MIO.LoadFromFileTIFF('Test.tif');

  ImageEnView1.Zoom := ImageEnView1.Zoom * Ratio;
end;

procedure TForm1.ImageEnView1ImageAtPos(Sender: TObject;
  var idx: Integer; x, y: Integer);
var
  VX, VY: Integer;
begin
  VX := ImageEnView1.ViewX;
  VY := ImageEnView1.ViewY;

  ImageEnView1.SelectedImage := idx;

  ImageEnView1.UpdateImage(idx);

  ImageEnView1.SetViewXY(VX, VY);

  VX := X + ImageEnView1.ViewX - ImageEnView1.ImageX[idx];
  VY := Y + ImageEnView1.ViewY - ImageEnView1.ImageY[idx];

  ImageEnView1.IEBitmap.IECanvas.MoveTo(VX, VY);

  ImageEnView1.IEBitmap.IECanvas.Pen.Width := 2;
  ImageEnView1.IEBitmap.IECanvas.Pen.Color := clBlack;
end;

procedure TForm1.ImageEnView1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  Drawing := True;
end;

procedure TForm1.ImageEnView1MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
var
  Index, VX, VY:integer;
begin
  if Drawing then
  begin
    Index := ImageEnView1.ImageAtPos(X, Y);

    VX := X + ImageEnView1.ViewX - ImageEnView1.ImageX[Index];
    VY := Y + ImageEnView1.ViewY - ImageEnView1.ImageY[Index];

    ImageEnView1.IEBitmap.IECanvas.LineTo(VX, VY);
    ImageEnView1.Update;
  end;
end;

procedure TForm1.ImageEnView1MouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  Drawing := False;
end;

end.


attach/jwhite/2015812135517_DrawTest.zip
102.24 KB
xequte Posted - Aug 05 2015 : 18:34:39
Hi

You can use ViewX and ViewY to find the first displayed column/row (not pixel based)

Or ImageX[] and ImageY[] to find the position of a particular thumbnail (pixel based).


If those do not meet your needs, please let us know what you are doing in more detail.

Nigel
Xequte Software
www.xequte.com
nigel@xequte.com