I am developing an application with iText 7 (7.1.14) to write a text on the top right of existing PDFs. Except that on some files, for example the one that can be downloaded from here, it gives me an incorrect page size. It happens with scanned PDFs. Page size returned 595.44 x 842.04. But the real one is 1656.0 x 2339.0. I tried with all the page sizes like MediaBox etc...
PdfDocument pdfDoc = new PdfDocument(pdfReader,new PdfWriter(file));
pageSize = page.getPageSize();
System.out.println("W:"+page.getPageSize().getWidth()+"H:"+page.getPageSize().getHeight());
System.out.println("W:"+page.getMediaBox().getWidth()+"H:"+page.getMediaBox().getHeight());
System.out.println("W:"+page.getCropBox().getWidth()+"H:"+page.getCropBox().getHeight());
System.out.println("W:"+page.getBleedBox().getWidth()+"H:"+page.getBleedBox().getHeight());
System.out.println("W:"+page.getArtBox().getWidth()+"H:"+page.getArtBox().getHeight());
To be precise, the rest of the code is this:
PdfFont bf = PdfFontFactory.createFont(FontConstants.HELVETICA);
float stringWidth = bf.getWidth(stringa,fontSize);
PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);
float centeredPosition = pageSize.getWidth() - (pageSize.getWidth()/30);
float yCoord = (pageSize.getHeight()-fontSize-5);
float xCoord = centeredPosition-stringWidth;
canvas.beginText().setFontAndSize(bf, fontSize)
.moveText(xCoord, yCoord)
.showText(stringa)
.setTextRenderingMode(pageN)
.endText();
pdfDoc.close();
In the linked example PDF, it is not positioned at the top right, but in the middle of the sheet. If I take a text PDF file, the result is correct.
You misinterpret the output of those getters. In particular they have nothing to do with pixels.
All these boxes are given in default user space units. One such unit is 1/72 inch unless it is redefined by the UserUnit entry of the respective page (A positive number that shall give the size of default user space units, in multiples of 1 ⁄ 72 inch. The range of supported values shall be implementation-dependent. - ISO 32000-2, Table 31 — Entries in a page object).
Concerning your added question concerning the addition of text to your PDF:
The reason why the position where your text is drawn is not where you expect it to be drawn, is that the user space coordinate system has been transformed in the original content stream:
0.36000 0 0 0.36000 0 0 cm
q
1656 0 0 2339 0 0 cm
/Im1 Do
Q
The first instruction (0.36000 0 0 0.36000 0 0 cm
) changes the current transformation matrix and so effectively scales the user coordinate system by .36; afterwards one user space unit is 1/200 inch.
The following instructions are wrapped in a q (save graphics state) ... Q (restore graphics state) envelope, so the change of the current transformation matrix therein doesn't influence any instructions thereafter.
To not be influenced at all by such graphics state changes by existing content stream instructions, you should yourself wrap existing, unknown content in another q ... Q envelope.
There actually is a PdfCanvas
constructor doing that for you; simply replace
PdfCanvas canvas=new PdfCanvas(page.newContentStreamAfter(),page.getResources(),pdfDoc);
by
PdfCanvas canvas=new PdfCanvas(page, true);
See also the JavaDocs of that constructor:
/**
* Convenience method for fast PdfCanvas creation by a certain page.
*
* @param page page to create canvas from.
* @param wrapOldContent true to wrap all old content streams into q/Q operators so that the state of old
* content streams would not affect the new one
*/
public PdfCanvas(PdfPage page, boolean wrapOldContent)
Beware, though: If you add multiple new content streams to a page, don't use true
for wrapOldContent
again and again for the same page; that would wrap the old content deeper and deeper into such envelopes, but PDF processors need only support a limited depth, PDF 32000-1 still mentioned a nesting limit of 28 wrappings.