Author |
Topic |
|
jwhite
8 Posts |
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.
|
|
xequte
38514 Posts |
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
|
|
|
jwhite
8 Posts |
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 |
|
|
w2m
USA
1990 Posts |
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
8 Posts |
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
USA
1990 Posts |
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 |
|
|
|
Topic |
|
|
|