1

I am using iTextSharp to place an image and some text on every page of a PDF. This works perfectly for some PDF's but not for others. Strangely enough it does not work for instance on a PDF I created with Word 2010's 'Save as pdf' function. I use GetOverContent, which should everything on top.

With Acrobat I can see that my layer has been added. So it must be under the word text somewhere.

How can I set a z-index for my stamp?

And is there a way (tool) to see clearly what objects are in a PDF? I find Acrobat not really helpfull in that regard, but maybe I need training ;-)

Example not working PDF here. (link updated)

Stamping code here, PDF comes from database and is stored in database:

Protected Sub cbTekening_Callback(source As Object, e As DevExpress.Web.CallbackEventArgs) Handles cbTekening.Callback
    Dim document As New iTextSharp.text.Document()
    Dim intTekID As Integer

    Try

        Dim fieldValues As List(Of Object) = gridTekeningen.GetSelectedFieldValues(New String() {"TekeningID"})

        For Each item As Object In fieldValues
            Using ms As MemoryStream = New MemoryStream()
                intTekID = item

                Dim pdfr = New PdfReader(GetPDFFromDatabase(intTekID).ToArray())

                Dim pdfs As New iTextSharp.text.pdf.PdfStamper(pdfr, ms)

                Dim image__1 As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(New System.Uri(Session("ORG_Website") & Session("ORG_Tekeninglogo")))
                Dim image__2 As iTextSharp.text.Image = iTextSharp.text.Image.GetInstance(New System.Uri(Session("ORG_Website") & "Images/contactid_" & Session("ContactID") & ".png"))
                Dim rect As Rectangle

                Dim PageCount As Integer = pdfr.NumberOfPages
                Dim content As iTextSharp.text.pdf.PdfContentByte
                For x = 1 To PageCount
                    rect = pdfr.GetPageSize(x)
                    content = pdfs.GetOverContent(x)

                    image__1.SetAbsolutePosition(50.0F, 50.0F)
                    image__1.ScalePercent(30.0F, 30.0F)
                    image__2.SetAbsolutePosition(100.0F, 100.0F)
                    image__2.ScalePercent(30.0F, 30.0F)
                    Content.AddImage(image__1)
                    Content.AddImage(image__2)
                    Dim layer As New PdfLayer("Goedkeurlaag" & x.ToString, pdfs.Writer)
                    'Tell the cb that the next commands should be "bound" to this new layer
                    Content.BeginLayer(layer)
                    Content.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 20)

                    Dim strWatermerkText1 As String = Session("ORG_Tekeningtekst")
                    Dim strWatermerkText2 As String = Format(Now, "dd-MM-yyyy")
                    Dim strWatermerkText3 As String = Session("VolNaam")

                    Content.SetColorFill(BaseColor.RED)
                    Content.BeginText()
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, 60, 160, 0.0F)
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, 60, 185, 0.0F)
                    Content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, 60, 210, 0.0F)
                    Content.EndText()

                    '// Close the layer
                    Content.EndLayer()                
                Next

                pdfs.Close()
                StoreToDatabase(ms, intTekID)

            End Using
        Next item

        imgPubliceerTekening.ClientVisible = False
        gridTekeningen.DataBind()

    Catch ex As Exception

    End Try
End Sub
Ronald
  • 45
  • 7
  • Possible duplicate of [How to add a watermark to a PDF file?](http://stackoverflow.com/questions/17522965/how-to-add-a-watermark-to-a-pdf-file) – Bruno Lowagie Nov 24 '15 at 16:03
  • The tool you need to inspect what's inside the PDF is called [iText RUPS](http://itextpdf.com/product/itext_rups). – Bruno Lowagie Nov 24 '15 at 16:08
  • @Bruno, I've been looking into that but could not find if my image was outside the viewing area. I will use the link for iText RUPS and will investigate more. The PDF I enclosed seems to work fine, apparently this was a database mishap, which caused the original version to be saved. I have other PDF's that do not work and will go from there. – Ronald Nov 25 '15 at 13:43
  • @Bruno do you have instructions on how to run the jar files? I have the latest Java but double click on the jar does nothing. – Ronald Nov 25 '15 at 14:07
  • You can run the .exe file. The jar should be executable too, but it depends on other jars and I don't remember which ones. I always use the exe. Or I run RUPS from my IDE (from the source code). – Bruno Lowagie Nov 25 '15 at 14:11
  • I managed to find the exe and run it on the PDF I've added above now (I changed the link). I'm not capable of making an assumption on the info I get from RUPS. Can you see what might be wrong with the new pdf? – Ronald Nov 27 '15 at 15:18

1 Answers1

4

Making it runnable

I made your example self-contained and runnable by removing all database and session object access. Additionally I translated it to C# which comes more naturally to me. As images I used our respective stackoverflow avatars and as texts the session object keys or format strings from which your code derives the string values:

void AddStamps(string OrigFile, string ResultFile)
{
    Document document = new Document();

    using (MemoryStream ms = new MemoryStream())
    {
        PdfReader pdfr = new PdfReader(OrigFile);
        PdfStamper pdfs = new PdfStamper(pdfr, ms);

        Image image__1 = Image.GetInstance(new System.Uri("https://www.gravatar.com/avatar/6bc6e4a08a5683b6f4ef8a8eb5117114?s=48&d=identicon&r=PG"));
        Image image__2 = Image.GetInstance(new System.Uri("https://www.gravatar.com/avatar/53d3aae5c986ca57f01016f5e0be82de?s=32&d=identicon&r=PG&f=1"));
        Rectangle rect;

        int PageCount = pdfr.NumberOfPages;
        PdfContentByte content;
        for (int x = 1; x <= PageCount; x++)
        {
            rect = pdfr.GetPageSize(x);
            content = pdfs.GetOverContent(x);

            image__1.SetAbsolutePosition(50.0F, 50.0F);
            image__1.ScalePercent(30.0F, 30.0F);
            image__2.SetAbsolutePosition(100.0F, 100.0F);
            image__2.ScalePercent(30.0F, 30.0F);
            content.AddImage(image__1);
            content.AddImage(image__2);
            PdfLayer layer = new PdfLayer("Goedkeurlaag", pdfs.Writer);
            content.BeginLayer(layer);
            content.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 20);

            String strWatermerkText1 = "ORG_Tekeningtekst";
            String strWatermerkText2 = "dd-MM-yyyy";
            String strWatermerkText3 = "VolNaam";

            content.SetColorFill(BaseColor.RED);
            content.BeginText();
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, 60, 160, 0.0F);
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, 60, 185, 0.0F);
            content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, 60, 210, 0.0F);
            content.EndText();

            content.EndLayer();
        }

        pdfs.Close();
        File.WriteAllBytes(ResultFile, ms.ToArray());
    }
}

Running it

Applying this method to your sample file the result looks like this:

Overview of all result pages

i.e. on each page the following stamp is clearly visible:

the visible stamp

Thus

As the stamp is clearly visible on your sample document and the translation VB to C# here was fairly faithful, the issue is caused by some factor you did not mention, e.g.

  • some exception occurs (probably during database access or due to some null value returned by the database or session) which you ignore with your

    Catch ex As Exception
    
    End Try
    

    empty catch block.

  • your images are completely transparent and your text is empty.

In general

So it must be under the word text somewhere.

If you add content to pdfs.GetOverContent(x), it is added after the existing content of that page, and as PDF does not know a z axis, any content drawn later covers content drawn earlier. Your new content can only be covered by

  • even newer content added later or
  • annotation content because all annotations by specification are above all regular content.

(Or, of course, it can be off-screen...)

Looking at the new sample document

The OP meanwhile has supplied a different sample document, and applying the code above to it indeed does not result in visible stamps.

But the cause has already hinted at above:

Or, of course, it can be off-screen...

The OP's code implicitly assumes that the coordinate system origin is in the lower left of the page. While this is often the case, it does not have to be so!

The OP's code already fetches the media box of the page:

rect = pdfr.GetPageSize(x)

Inspecting this media box for the document at hand, one sees that its lower left corner is (0, -836.64001) and its top right corner is (1207.68005, 0). Thus, the origin is in the top left corner and all the coordinates the OP used are above the visible page.

If one replaces the corresponding lines in the C# code above by:

image__1.SetAbsolutePosition(rect.Left + 50.0F, rect.Bottom + 50.0F);
...
image__2.SetAbsolutePosition(rect.Left + 100.0F, rect.Bottom + 100.0F);
...
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText3, rect.Left + 60, rect.Bottom + 160, 0.0F);
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText2, rect.Left + 60, rect.Bottom + 185, 0.0F);
content.ShowTextAligned(PdfContentByte.ALIGN_LEFT, strWatermerkText1, rect.Left + 60, rect.Bottom + 210, 0.0F);

one again gets the desired stamps:

on-screen stamps

mkl
  • 90,588
  • 15
  • 125
  • 265
  • Thanks for your clear explanation. As I've stated in my answer to Bruno, the PDF did work fine. But there are PDF's that still do not work ok. Can you give this one a try? [link]http://www.n-tree.biz/download/test.pdf ? – Ronald Nov 27 '15 at 12:51
  • @Ronald See above, you have to consider the coordinate system used on the page at hand... – mkl Nov 27 '15 at 17:01
  • As proven by @mkl, the question *was indeed a duplicate*. The coordinate system was ignored. – Bruno Lowagie Nov 27 '15 at 18:22
  • @mkl, thank you very much for your time investigating and solving this. I put your changes in my code and it works perfectly for all my test PDF's now. With my knowledge I was not able to determine if it was a duplicate question, because for an outsider it's not always easy to project a suggested solution on your own problem. It is very much appreciated that you (mkl) and Bruno take the time to help someone in need. – Ronald Nov 30 '15 at 14:33