10

I'm using C# and iTextSharp to add a watermark to my PDF files:

Document document = new Document();
PdfReader pdfReader = new PdfReader(strFileLocation);
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(strFileLocationOut, FileMode.Create, FileAccess.Write, FileShare.None));
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(WatermarkLocation);
img.SetAbsolutePosition(100, 300);
PdfContentByte waterMark;
//    
for (int pageIndex = 1; pageIndex <= pdfReader.NumberOfPages; pageIndex++)
{
    waterMark = pdfStamper.GetOverContent(pageIndex);
    waterMark.AddImage(img);
}
//
pdfStamper.FormFlattening = true;
pdfStamper.Close();

It works fine, but my problem is that in some PDF files no watermark is added although the file size increased, any idea?

Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
Abady
  • 111
  • 1
  • 2
  • 10
  • Do all of your PDF files have the same mediabox and cropbox? Could it be that the position `(100, 300)` is outside these boxes? – Alexis Pigeon Jul 08 '13 at 10:03
  • the position is correct, i test it. – Abady Jul 08 '13 at 10:10
  • And what are the coordinates of the media/crop boxes when no watermark is visible? – Alexis Pigeon Jul 08 '13 at 10:10
  • Where can i get media/crop coordinates? – Abady Jul 08 '13 at 10:16
  • The example [PageInformation.cs](http://kuujinbo.info/iTextInAction2Ed/index.aspx?ch=Chapter06&ex=PageInformation) shows you how to retrieve page information, e.g. the mediabox. – mkl Jul 08 '13 at 15:45
  • Read http://stackoverflow.com/questions/17439520/how-to-position-text-relative-to-page-using-itext/17442368#17442368 and you'll notice that your code ignores any MediaBox and CropBox information that may be present in the PDF. I'll edit your question as it's not fair to state that something in iTextSharp is "not working". That sounds as if there's a bug in iText whereas it's actually a bug in your code ;-) – Bruno Lowagie Jul 08 '13 at 16:07
  • @Abady what is parameter WatermarkLocation? – 3 rules Oct 20 '16 at 11:28

2 Answers2

8

The fact that the file size increases is a good indication that the watermark is added. The main problem is that you're adding the watermark outside the visible area of the page. See How to position text relative to page using iText?

You need something like this:

Rectangle pagesize = reader.GetCropBox(pageIndex);
if (pagesize == null)
    pagesize = reader.GetMediaBox(pageIndex);
img.SetAbsolutePosition(
    pagesize.GetLeft(),
    pagesize.GetBottom());

That is: if you want to add the image in the lower-left corner of the page. You can add an offset, but make sure the offset in the x direction doesn't exceed the width of the page, and the offset in the y direction doesn't exceed the height of the page.

Community
  • 1
  • 1
Bruno Lowagie
  • 75,994
  • 9
  • 109
  • 165
  • 1
    In iText LGPL ver 4.1.6 in Nuget, there is no `pdfReader.GetMediaBox(pageNumber)`, instead there is `pdfReader.GetPageSize(pageNumber)`. Also `pageIndex` gives the impression it starts with `0`. Since it starts with `1`, `pageNumber` would be better. – Rosdi Kasim Apr 02 '15 at 10:07
  • @RosdiKasim while I disagree that pageIndex implies 0-based indexing, you're correct that GetMediaBox() is the wrong method.... you should add this edit to the answer so it will be more correct. GetCropBox is also the correct casing of getCropBox – Arkaine55 May 15 '15 at 19:58
0

Although I don't know the specifics of iTextSharp, likely on the pages where your image is not showing, the previous PDF content has modified the current transformation matrix such that whatever you put on the page is moved off the page.

This can be fixed by emitting a gsave operator before the original page content and emitting a grestore operator after the original page content (but before yours). This, however may not fix all cases with a PDF document that modifies the CTM does a gsave and no grestore. This is not supposed to happen in theory, according to the PDF specification:

Occurrences of the q and Q operators shall be balanced within a given content stream (or within the sequence of streams specified in a page dictionary’s Contents array).

but I can tell you from experience that this is not the case in practice.

plinth
  • 48,267
  • 11
  • 78
  • 120
  • The OP uses `pdfStamper.GetOverContent` which means that iText envelops the existing content stream in **q** and **Q** and adds the OP's additions afterwards, outside the **q ... Q** and, therefore, not influenced by any such CTM changes. I assume @Alexis is right in his assumption. – mkl Jul 08 '13 at 13:46