I am using PDFBox for generating a pdf from one of my user inputted forms. For drawing a line I am using PDPageContentStream.drawLine and for text PDPageContentStream.drawString. The text works perfect but while using drawLine, when I try to print the pdf, I get the error as shown in the attached Image. My code looks like this
PDPage page = new PDPage();
release.addPage(page);
contentStream = new PDPageContentStream(release,page);
int margin = 40;
vertHeight -= thisFontHeight * fontSize * 1.05f + 5;
contentStream.drawLine(margin,vertHeight + margin - 5, page.getMediaBox().getWidth() - margin, vertHeight + margin - 5)
Any help appreciated
Your code sample doesn't show it, but I suspect you're mixing lines and text. You must not draw lines between BT and ET.
begin Text
draw some text
end text
draw a line
begin text
draw some text
end text
draw some more lines
etc
If you drew a line between 1 and 3, for example, you'd get the above error (or one similar to it).
PS: If that's not it, we'll need a sample PDF to diagnose the issue.
Related
I have a script that creates a PDF file and writes contents to it. After the execution is complete I need to write the status (fail, success) to the PDF, but the status should be on the top of the page. So the solution I came up with is to use absolute positioned text. Below is my code for the same
PdfContentByte cb = writer.DirectContent;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.SaveState();
cb.BeginText();
cb.MoveText(700, 30);
cb.SetFontAndSize(bf, 12);
cb.ShowText("My status");
cb.EndText();
cb.RestoreState();
But as the PDF creates multiple pages, this is added to the last page of the PDF. How can I add it to the 1st page??
Also is there a way to calculate the top coordinates of the page, ie the top-left coordinate?
iText was written with internet applications in mind. It was designed to flush content from memory as soon as possible: if a page is finished, that page is sent to the OutputStream and there is no way to return to that page.
That doesn't mean your requirement is impossible. PDF has a concept known as Form XObject. In iText, this concept is implemented under the name PdfTemplate. Such a PdfTemplate is a rectangular canvas with a fixed size that can be added to a page without being part of that page.
An example should clarify what that means. Please take a look at the WriteOnFirstPage example. In this example, we create a PdfTemplate like this:
PdfContentByte cb = writer.getDirectContent();
PdfTemplate message = cb.createTemplate(523, 50);
This message object refers to a Form XObject. It is a piece of content that is external to the page content.
We wrap the PdfTemplate inside an Image object. By doing so, we can add the Form XObject to the document just like any other object:
Image header = Image.getInstance(message);
document.add(header);
Now we can add as much data as we want:
for (int i = 0; i < 100; i++) {
document.add(new Paragraph("test"));
}
Adding 100 "test" lines will cause iText to create 3 pages. Once we're on page 3, we no longer have access to page 1, but we can still write content to the message object:
ColumnText ct = new ColumnText(message);
ct.setSimpleColumn(new Rectangle(0, 0, 523, 50));
ct.addElement(
new Paragraph(
String.format("There are %s pages in this document", writer.getPageNumber())));
ct.go();
If you check the resulting PDF write_on_first_page.pdf, you'll notice that the text we've added last is indeed on the first page.
With the follow code I open a PDF file (with filechooser object, I don't show all the code here, it's not important) and then I "put" everything in a List od PDPage, where there are all the PDF pages . If the PDF has 3 pages I will have 3 images , if the PDF has 4 pages I will have 4 images , etc ..
PDDocument document2 = PDDocument.loadNonSeq(new File(pdfFile), null);
List<PDPage> pdPages = document2.getDocumentCatalog().getAllPages();
In order to convert in BufferedImage I do this:
for (PDPage pdPage : pdPages)
{
++page;
BufferedImage bim = pdPage.convertToImage(BufferedImage.TYPE_INT_RGB, 300);
ImageIOUtil.writeImage(bim, pdfFile + "-" + page + ".png", 300);
}
and then I show, for example, one page in a stackpane. Now the problem, I want to show a preview of pdPages(so, no image format but PDPage) because I think is much better for big PDF. I mean, if I want to "convert" a PDF with 200 pages, it will take long time to complete the task. I thought to show a preview (maximum 10 or 15, it's not important) of the pages(in this way the user will click the interested image) but in PDPage format, not yet Image converted. I am thinking in the right way or I am wrong? In positive case, what can I do ?
Thanks in advance
I am attempting to view a pdf through a JFrame that contains a PDFPagePanel. While I can view the PDF, it is smaller than the actual page and therefore it appears fuzzy at best. I need the document in the full resolution and size that it is. I do NOT want to turn this into an image. I need it to stay a PDF onscreen. Here is the code I am using:
protected PDDocument originalDoc;
protected PDPage memDoc;
protected PDFPagePanel pdfPanel; // initialized in constructor
....
List<PDPage> memPDF = originalDoc.getDocumentCatalog().getAllPages();
memDoc = memPDF.get(0);
pdfPanel.setPage(memDoc);
add(pdfPanel);
setBounds(1, 1, pdfPanel.getWidth(), pdfPanel.getHeight() + 51); // set JFrame to fit the size of the document + dropdown menu
pdfPanel.setVisible(true);
I get the PDF onscreen. It's not the correct size, though. The page itself is 8.5" x 11" and when I view it in Adobe PDF the "image" is fine and is very readable. It is very obviously not scaled correctly on the screen and I cannot find any solutions as to why? This is not the same as converting this to a BufferedImage which are the solutions I see online. I need it to stay in PDPage format and display that in the PDFPagePanel class.
I've been trying to add annotations to an existing PDF using the iText API and the older Lowagie version. However, I need alternatives to the API since it does not seem to be able to do what is asked in our requirement.
The requirement is to put an Annotation into an existing PDF with the following details:
Type: plain text
Postion: x=0mm && y=0mm
Font: Arial
Text Colour: White
Text Content: "some text"
Using iText, I can put in an annotation but I need to approximate in pixels where in my A4 size page I should put it. The closest approximation is using
PdfReader reader = new PdfReader(headerFilePath.concat(xmlFileName));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(headerFilePath.concat(xmlFileNameNew)));
PdfAnnotation annotation = PdfAnnotation.createText(stamper.getWriter(), new Rectangle(0, 842, 5, 842), "some text", "some text", true, null);
annotation.setColor(Color.WHITE);
stamper.addAnnotation(annotation, 1);
reader.close();
stamper.close();
This snippet places it at the top left corner but I'm not sure if it's 0mm,0mm. Also it is black and I cannot specify the font.
Any help on the matter is greatly appreciated. Thanks!
You may try rich text annotions as described here:
annotation.put(PdfName.RC, new PdfString( "<font size=\"whatever\">" +
some text+
"</font>" ) );
myStamper.setGenerateAppearances( false );
However I doubt that this is what you need. If you add an appearance then you'll get an rectangular icon in the upper left corner. If you then hover with you mouse over it you are able to read the annotation in form of a pop up. And even if you get a white font color of the annotation text you can't hide the rectangular icon of the annotation itself...
You want to have a white font color which indicates that you want to "transport" some hidden (white color on white background) information. Maybe in this case you may use the following mechanism ( which is normally used for adding watermarks etc.):
String text;
int pageNumber
PdfContentByte overContent = stamper.getOverContent(pageNumber);
overContent.beginText();
overContent.setFontAndSize(yourFont, yourFontSize);
//overContent.setGrayFill(...);
overContent.showTextAligned(PdfContentByte.ALIGN_CENTER, yourText + " Center", 150, 760, 0);
overContent.endText();
Update: To set an annotation to invisble add to your code:
annotation.setColor(Color.WHITE);
//set visibility to 0 (invisble). All values between 0...1 are possible
//so 0.5 means 50% opacity
annotation.put(PdfName.CA, new PdfNumber(0));
I am trying to create a pdf/a file from a pdf file using itext. Everything goes fine and I get a pdf/a file. But when I check it here http://www.pdf-tools.com/pdf/validate-pdfa-online.aspx I get an error like
The width for character 1 in font 'ArialRegular' does not match.
The width for character 2 in font 'ArialRegular' does not match.
The width for character 3 in font 'ArialRegular' does not match.
how could I solve this error?
PdfReader pdfReader = new PdfReader(file);
FontFactory.defaultEmbedding = true;
BaseFont bf = BaseFont.createFont(FONT, BaseFont.CP1252, BaseFont.EMBEDDED);
while (currentpagenumber < pdfReader.getNumberOfPages()) {
document.newPage();
currentpagenumber++;
finalpagenumber++;
page = pdfAWriter.getImportedPage(pdfReader, currentpagenumber);
cb.addTemplate(page, 0, 0);
cb.beginText();
cb.setFontAndSize(bf, 18);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, finalpagenumber+"", 520, 5, 0);
cb.endText();
ICC_Profile icc = ICC_Profile.getInstance(new FileInputStream(PROFILE));
this is the basic code. I also tried to find the font used in each page using pdfdictionary .. and tried to embeded it as base font.. but couldnot work..
Never used IText before, but just looking at doing a similar conversion now, and it appears to be a bug in the library and not in the way you are using it.
The best option I can give you is to report a bug at:
http://sourceforge.net/p/itext/bugs/
The IText mailing list would also be another place to try.
md_5