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

137 views
Skip to first unread message

paolo capirci

unread,
Feb 13, 2015, 5:31:25 AM2/13/15
to pdfne...@googlegroups.com
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()));
}
}
}

Ryan

unread,
Feb 13, 2015, 6:08:59 PM2/13/15
to pdfne...@googlegroups.com
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);


paolo capirci

unread,
Feb 17, 2015, 6:36:30 AM2/17/15
to pdfne...@googlegroups.com
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);

Ryan

unread,
Feb 24, 2015, 6:05:19 PM2/24/15
to pdfne...@googlegroups.com
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);
        }
    }
}


paolo capirci

unread,
Feb 25, 2015, 12:32:03 PM2/25/15
to pdfne...@googlegroups.com
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.

Ryan

unread,
Feb 25, 2015, 1:33:35 PM2/25/15
to pdfne...@googlegroups.com
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.

paolo capirci

unread,
Mar 11, 2015, 1:31:40 PM3/11/15
to pdfne...@googlegroups.com
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

Ryan

unread,
Mar 12, 2015, 1:42:23 PM3/12/15
to pdfne...@googlegroups.com
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
.StampImage(mPDFView.GetDoc(), img, new PageSet(pageNumber));

}
Annot annot = page.GetAnnot(page.GetNumAnnots() - 1);

mPDFView
.DocUnlock();

Config cfg = mPDFView.GetDoc().GetOCGConfig();

Context ocg_ctx = new Context(cfg);

mPDFView
.SetOCGContext(ocg_ctx);

mPDFView
.Update();


Reply all
Reply to author
Forward
0 new messages