Stamper.SetPosition accuracy and refreshing to see a new stamper added

A couple of question:
1) after adding a stamper to a page, I don't see it. If a save, close and re-open that file, I see it. How can I see that stamper as soon as I have added it to a page?
2) The method SetPosition(x, y) it seems to be not precise. I post my code hereafter to verify if I have missed something. Please note that I have a button to choose the stamp image, and after the click event, I call a second event on mouse down in order to have the correct position where I have to add, as annotation, that image/stamp. But that stamp appear at a wrong place, w.r.t. the mouse position.

        private void btnPass_Clicked(object sender, RoutedEventArgs e)
        {
            PDFViewViewer view = GetCurrentViewer();
            if (view != null)
            {
                view.MouseDown += view_MouseDown;
            }
        }

        void view_MouseDown(object sender, MouseButtonEventArgs e)
        {
            PDFViewViewer view = (PDFViewViewer) sender;
            PDFDoc doc = view.GetPDFDoc();
            if (doc != null)
            {
                System.Windows.Point position = e.GetPosition(view);
                double x = position.X;
                double y = position.Y;
                view.Current_View.ConvScreenPtToPagePt(ref x, ref y, view.GetCurrentPageNumber());

                using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
                {
                    Image img = Image.Create(doc, @"..\..\Images\Pass.png");
                    s.SetAsBackground(false);
                    s.SetPosition(x, y);
                    s.SetAsAnnotation(true);
                    s.StampImage(doc, img, new PageSet(view.GetCurrentPageNumber()));
                }
            }
        }

Hi, regarding the first one, our Stamps are added as a layer, so you need to update the viewer (Stamper and Viewer classes are disconnected in this sense).

`

Config cfg = doc.GetOCGConfig();
Context ocg_ctx = new Context(cfg);
view.SetOCGContext(ocg_ctx);

`

Regarding the stamp location, try the following.

System.Windows.Point position = e.GetPosition(view.Current_View);

Hi Ryan,
it seems still doesn’t work (both the above points). I post my code again, after the suggested changes. The only thing I am not sure is where I have to “bind” Stamper and Viewer classes.
Anyway I have moved the code snippet you have posted, before and after the using Stamper clause, without any different behaviour of the WPF form:

private void view_MouseDown(object sender, MouseButtonEventArgs e)
{
PDFViewViewer view = (PDFViewViewer)sender;
PDFViewWPF currentView = view.Current_View;
const string folder = @"…\Images";
string imageFile = view.StampName + “.png”;
PDFDoc doc = view.GetPDFDoc();
if (doc != null)
{
try
{
System.Windows.Point position = e.GetPosition(currentView);
double x = position.X;
double y = position.Y;
currentView.ConvScreenPtToPagePt(ref x, ref y, currentView.CurrentPageNumber);

Config cfg = doc.GetOCGConfig();
Context ocg_ctx = new Context(cfg);
currentView.SetOCGContext(ocg_ctx);

using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
{
Image img = Image.Create(doc, folder + imageFile);
s.SetAsBackground(false);
s.SetPosition(x, y);
s.SetAsAnnotation(true);
s.StampImage(doc, img, new PageSet(currentView.CurrentPageNumber));
}
}
catch (PDFNetException ex)
{
MessageBox.Show("PDFNet Exception: " + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show("General Exception: " + ex.Message);
}
}
}
Il giorno sabato 14 febbraio 2015 00:08:59 UTC+1, Ryan ha scritto:

Hi, regarding the first one, our Stamps are added as a layer, so you need to update the viewer (Stamper and Viewer classes are disconnected in this sense).

`

Config cfg = doc.GetOCGConfig();
Context ocg_ctx = new Context(cfg);
view.SetOCGContext(ocg_ctx);

`

Regarding the stamp location, try the following.

System.Windows.Point position = e.GetPosition(view.Current_View);

The issue is that by default Stamper is using centered vertical and horizontal alignment. You can see this by calling SetPosition(0,0) and the image will be in the middle of the page, instead of the bottom left corner. So your Stamp was being put off screen most likely.

The following code is what you want in your case.

`
private void view_MouseDown(object sender, MouseButtonEventArgs e)
{
PDFViewViewer view = (PDFViewViewer)sender;
PDFViewWPF currentView = view.Current_View;
const string folder = @"…\Images";
string imageFile = view.StampName + “.png”;

PDFDoc doc = view.GetPDFDoc();
if (doc != null)
{
try
{
System.Windows.Point position = e.GetPosition(currentView);

double x = position.X;
double y = position.Y;
currentView.ConvScreenPtToPagePt(ref x, ref y, currentView.CurrentPageNumber);

mPDFView.DocLock(true);

using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
{
Image img = Image.Create(doc, folder + imageFile);
s.SetAsBackground(false);
s.SetTextAlignment(Stamper.TextAlignment.e_align_left);
s.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_left, Stamper.VerticalAlignment.e_vertical_bottom);
s.SetPosition(x, y);
s.SetAsAnnotation(true);
s.StampImage(doc, img, new PageSet(currentView.CurrentPageNumber));
}

Config cfg = doc.GetOCGConfig();
Context ocg_ctx = new Context(cfg);
currentView.SetOCGContext(ocg_ctx);

currentView.DocUnlock();

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// since you are adding the stamp as an annotation, you can get the annot bounding box and just update that area (as an optimization)
Page page = currentView.GetDoc().GetPage(currentView.CurrentPageNumber);
Annot annot = page.GetAnnot(page.GetNumAnnots() -1 ); // annots are always added to the end of the list, so this will be the stamp.
currentView.Update(annot, currentView.CurrentPageNumber);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if not adding as annotation, you need to call regular update
//currentView.Update();
}
catch (PDFNetException ex)
{
MessageBox.Show("PDFNet Exception: " + ex.Message);
}
catch (Exception ex)
{
MessageBox.Show("General Exception: " + ex.Message);
}
}
}
`

Great! Now the position accuracy works perfectly; also the refresh is OK in both the situations (Annot or not).
Just to give a better feeling to the user: as the stamp/image now is aligned right/bottom (e.g. the click/touch set the bottom/left image’s corner), I added x,y offset values in terms of 16.0, i.e. the half image’s dimensions.
Thank you for your help.
Il giorno venerdì 13 febbraio 2015 11:31:25 UTC+1, paolo capirci ha scritto:

A couple of question:

  1. after adding a stamper to a page, I don’t see it. If a save, close and re-open that file, I see it. How can I see that stamper as soon as I have added it to a page?
  2. The method SetPosition(x, y) it seems to be not precise. I post my code hereafter to verify if I have missed something. Please note that I have a button to choose the stamp image, and after the click event, I call a second event on mouse down in order to have the correct position where I have to add, as annotation, that image/stamp. But that stamp appear at a wrong place, w.r.t. the mouse position.

private void btnPass_Clicked(object sender, RoutedEventArgs e)
{
PDFViewViewer view = GetCurrentViewer();
if (view != null)
{
view.MouseDown += view_MouseDown;
}
}

void view_MouseDown(object sender, MouseButtonEventArgs e)
{
PDFViewViewer view = (PDFViewViewer) sender;
PDFDoc doc = view.GetPDFDoc();
if (doc != null)
{
System.Windows.Point position = e.GetPosition(view);
double x = position.X;
double y = position.Y;
view.Current_View.ConvScreenPtToPagePt(ref x, ref y, view.GetCurrentPageNumber());

using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
{
Image img = Image.Create(doc, @"…\Images\Pass.png");
s.SetAsBackground(false);
s.SetPosition(x, y);
s.SetAsAnnotation(true);
s.StampImage(doc, img, new PageSet(view.GetCurrentPageNumber()));
}
}
}

Great to hear.

Regarding the offset value of half the image dimension, you might instead want to try setting the horizontal alignment to center, and I think Stamper will figure the number out for you.

Hi Ryan,
I’m sorry but the stamper accuracy works perfectly only over the first document’s page (previously I have given my positive answer without going through the whole document, I’m sorry). When I go through the document, again the stamper is no more accurate. Well it’s better now, but still I click on a point and the stamper appears far away (but still on the page). Normally upper w.r.t. the mouse click point (or touch point on the tablet as well). Please note that the x/y offset values are not responsible of this behaviour (I tried to comment those lines, of course).
Here is my final code version (leaving off try/catch and if doc != null):

PDFViewViewer view = (PDFViewViewer) sender;
const string folder = @"…\Images";
string imageFile = view.StampName + “.png”;
PDFViewWPF currentView = view.Current_View;
PDFDoc doc = currentView.GetDoc();

System.Windows.Point position = e.GetPosition(currentView);
double x = position.X;
double y = position.Y;
currentView.ConvScreenPtToPagePt(ref x, ref y, currentView.CurrentPageNumber);
x -= XOffset;
y -= YOffset;
currentView.DocLock(true);

using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
{
Image img = Image.Create(doc, folder + imageFile);
s.SetAsBackground(false);
s.SetTextAlignment(Stamper.TextAlignment.e_align_left);
s.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_left,
Stamper.VerticalAlignment.e_vertical_bottom);
s.SetPosition(x, y);
s.SetAsAnnotation(true);
s.StampImage(doc, img, new PageSet(currentView.CurrentPageNumber));
}

Config cfg = doc.GetOCGConfig();
Context ocgCtx = new Context(cfg);
currentView.SetOCGContext(ocgCtx);
currentView.DocUnlock();
// since you are adding the stamp as an annotation, you can get the annot bounding box and just update that area (as an optimization)
pdftron.PDF.Page page = currentView.GetDoc().GetPage(currentView.CurrentPageNumber);
Annot annot = page.GetAnnot(page.GetNumAnnots() - 1); // annots are always added to the end of the list, so this will be the stamp.
currentView.Update(annot, currentView.CurrentPageNumber);
// if not adding as annotation, you need to call regular update
//currentView.Update();

Any further suggestion?
Thank you
Paolo
Il giorno mercoledì 25 febbraio 2015 19:33:35 UTC+1, Ryan ha scritto:

Great to hear.

Regarding the offset value of half the image dimension, you might instead want to try setting the horizontal alignment to center, and I think Stamper will figure the number out for you.

Hi, yes I see the issue. The call to SetPosition I thought was in page coordinates, but it actually takes into account page rotation and crop box.
http://www.pdftron.com/pdfnet/docs/PDFNet/?topic=html/M_pdftron_PDF_Stamper_SetPosition.htm

Add the following line of code after ConvScreenPtToPagePt.

Matrix2D mtx = page.GetDefaultMatrix();
mtx.Mult(ref x, ref y);

So final code is.

UIPoint point = GetPosition(e, mPDFView);
int pageNumber = mPDFView.GetPageNumberFromScreenPt(point.X, point.Y);
if (pageNumber == 0) return;
Image img = Image.Create(mPDFView.GetDoc(), path_to_image);
double x = point.X;
double y = point.Y;
Page page = mPDFView.GetDoc().GetPage(pageNumber);
mPDFView.ConvScreenPtToPagePt(ref x, ref y, pageNumber);
Matrix2D mtx = page.GetDefaultMatrix();
mtx.Mult(ref x, ref y);
mPDFView.DocLock(true);
using (Stamper s = new Stamper(Stamper.SizeType.e_absolute_size, 32, 32))
{
	s.SetAlignment(Stamper.HorizontalAlignment.e_horizontal_left, Stamper.VerticalAlignment.e_vertical_bottom);
	s.SetPosition(x, y);
	s.SetAsAnnotation(true); // optional
	s.StampImage(mPDFView.GetDoc(), img, new PageSet(pageNumber));
}
Annot annot = page.GetAnnot(page.GetNumAnnots() - 1); // if SetAsAnnotation(true) then this line of code gets the annotation if you want to make further changes.
mPDFView.DocUnlock();
Config cfg = mPDFView.GetDoc().GetOCGConfig();
Context ocg_ctx = new Context(cfg);
mPDFView.SetOCGContext(ocg_ctx);
mPDFView.Update();

Here is PHP code doing same task, stamping an image to a specific location.

<?php
include("../../../PDFNetC/Lib/PDFNetPHP.php");
// Relative path to the folder containing the test files.
$input_path = getcwd()."/../../TestFiles/";
$output_path = $input_path."Output/";
$input_filename = "newsletter";

	PDFNet::Initialize();
	PDFNet::GetSystemFontList();    // Wait for fonts to be loaded if they haven't already. This is done because PHP can run into errors when shutting down if font loading is still in progress.
	$bbox = new Rect(72.0, 272.0, 144.0, 344.0);
	$doc = new PDFDoc($input_path.$input_filename.".pdf");
	$doc->InitSecurityHandler();
	$page = $doc->GetPage(1);
	$mtx = $page->GetDefaultMatrix();
	$point = new Point($bbox->GetX1(), $bbox->GetY1());
	$point2 = $mtx->Mult($point);

	$img = Image::Create($doc->GetSDFDoc(), $input_path."butterfly.png");

	$stamper = new Stamper(Stamper::e_absolute_size, $bbox->Width(), $bbox->Height());
	$stamper->SetAlignment(Stamper::e_horizontal_left, Stamper::e_vertical_bottom);
	//$stamper->SetPosition($x, $y);
	$stamper->SetPosition($point2->__get("x"), $point2->__get("y"));
	$ps = new PageSet(1);
	$stamper->StampImage($doc, $img, $ps);
	$doc->Save($output_path.$input_filename.".ex1.pdf", SDFDoc::e_linearized);
	$doc->Close();
?>