This question already has an answer here:
How to update a PDF without creating a new PDF?
(1 answer)
Closed 6 years ago.
I have been trying to add an image to a PDF document using iText 7.
The function I have created to add the image takes a ImageData type and then adds it to a rectangle on a canvas and add that to a PDF. however, I keep getting the error
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
and then
Caused by: java.io.FileNotFoundException: pdf.pdf (The requested operation cannot be performed on a file with a user-mapped section open)
The function code is:
protected void ExportToPdf(ImageData img) throws IOException {
PdfDocument pdfDoc = new PdfDocument(new PdfReader("pdf.pdf"), new PdfWriter("pdf.pdf"));
PdfCanvas canvas = new PdfCanvas(pdfDoc.getFirstPage());
PageSize ps = PageSize.A4;
Rectangle page = new Rectangle(ps.getWidth(),ps.getHeight());
canvas.addImage(img, page, true);
pdfDoc.close();
`
And my main is as follows:
public static void main(String[] args) throws IOException { //adds values to maps for the program to use
//starts PDF writer
PdfWriter writer = new PdfWriter("pdf.pdf");
//Initialize PDF document
PdfDocument pdf = new PdfDocument(writer);
// Initialize document
Document document = new Document(pdf);
pdf.addNewPage();
document.close();
writer.close();
pdf.close();
The full program takes a scene and converts it into an image and then feeds it into the function to be added to the PDF. The code for that is:
WritableImage img = new WritableImage(1000, 700);
scene.snapshot(img);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(img, null);
ImageData imgData = ImageDataFactory.create(SwingFXUtils.fromFXImage(img, null), null);
ExportToPdf(imgData);
Any help would be amazing, thank you.
The problem is already here
PdfDocument pdfDoc = new PdfDocument(new PdfReader("pdf.pdf"), new PdfWriter("pdf.pdf"));
Itext does not support writing to the same file you are reading from. Simply instead write to a temporary file and replace the original file with it when finished.
Related
i'm new to itext 7. I have a list of documents with different content that I want to merge into a single PDF. The content types are PDF, JPG & PNG.
My problem is that as soon as I merge a PDF and an image, the image is written over the already inserted content of the target PDF.
How do I get each image to be added to a new page of the target PDF?
This is my Code:
byte[] mergeInhalt(List<Dokument> dokumentList) throws IOException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
PdfWriter pdfWriter = new PdfWriter(byteOut);
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
Document completeDocument = new Document(pdfDocument);
for (Dokument dokument : dokumentList) {
byte[] inhalt = dokument.getInhalt();
if (Objects.nonNull(inhalt)) {
switch (dokument.getFormat().name()) {
case "PDF":
addPdf(pdfDocument, inhalt);
break;
case "JPG":
case "PNG":
ImageData data = ImageDataFactory.create(inhalt);
Image image = new Image(data);
completeDocument.add(image);
break;
}
}
}
completeDocument.close();
return byteOut.toByteArray();
}
private void addPdf(PdfDocument pdfDocument, byte[] inhalt) throws IOException {
PdfReader pdfReader = new PdfReader(new ByteArrayInputStream(inhalt));
PdfDocument pdfDocumentToMerge = new PdfDocument(pdfReader);
pdfDocumentToMerge.copyPagesTo(1, pdfDocumentToMerge.getNumberOfPages(), pdfDocument);
}
Merging PDFs only works well, but everytime i merge a Image i get this:
The image with the pink one was placed over the text of the previous PDF
In your code you add the image via the Document completeDocument but you add the pdf via the underlying PdfDocument pdfDocument. Thus, the completeDocument doesn't know about the added pdf, continues on its current page, and draws over the imported pages.
To make sure each image is added on a new page after the currently last one, you have to tell completeDocument to move its current page:
case "JPG":
case "PNG":
ImageData data = ImageDataFactory.create(inhalt);
Image image = new Image(data);
completeDocument.add(new AreaBreak(AreaBreakType.LAST_PAGE));
completeDocument.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
completeDocument.add(image);
break;
For an example compare the tests testMergeLikeAndreasHuber and testMergeLikeAndreasHuberImproved in CopyPdfsAndImages and their outputs.
This question already has answers here:
Table disappears when drawn before contentStream - PDFBox with Boxable
(1 answer)
PDFBox : PDPageContentStream's append mode misbehaving
(1 answer)
Cannot figure out how to use PDFBox
(2 answers)
Closed 3 years ago.
I'm trying to save an image into an existing pdf using apache PDFBOX,but my contents are getting deleted and i get blank document when I place the image on top of the pdf,Is there a solution to the problem?
My Code Looks like this.
public class TestPdfImage {
public static void main(String args[]) throws Exception {
//Loading an existing document
File file = new File("...../mydoc.pdf");
PDDocument doc = PDDocument.load(file);
//Retrieving the page
PDPage page = doc.getPage(0);
//Creating PDImageXObject object
PDImageXObject pdImage = PDImageXObject.createFromFile("...../sample.png",doc);
//creating the PDPageContentStream object
PDPageContentStream contents = new PDPageContentStream(doc, page);
//Drawing the image in the PDF document
contents.drawImage(pdImage, 70, 250);
System.out.println("Image inserted");
//Closing the PDPageContentStream object
contents.close();
//Saving the document
doc.save(".../sample.pdf");
//Closing the document
doc.close();
}
}
Try to use the append-mode
//creating the PDPageContentStream object
PDPageContentStream contents = new PDPageContentStream(doc, page, AppendMode.APPEND, true);
Edit
TilmanHausherr mentioned
new PDPageContentStream(doc, page, AppendMode.APPEND, true, true);
Thats why
I have an existing pdf file that i'm reading with pdfreader and using pdfstamper to add some images and text into the temporary pdf file. The problem I'm facing is that Images are getting added to contentbyte but some of them are not visible and some of those are getting overlapped with each other as my scenario is to add screenshot to this pdf file after some point(at every failed step while running my selenium webdriver).I've tried setting different positions but nothing worked perfectly. I need to resolve this issue on priority.Please suggest what should i do to add image at bottom of existing pdf every time it needs to be added.
PdfReader pdfReader = new PdfReader(sScreenShotFileName);
PdfStamper pdfStamper = new PdfStamper(pdfReader,new
FileOutputStream(tempfile));
PdfContentByte content = pdfStamper.getUnderContent(i);
Font f = new Font();
f.setStyle(Font.BOLD);
f.setSize(8);
ColumnText ct = new ColumnText( content );
ct.setText(new Phrase(new SimpleDateFormat("MM-dd-YYYY HH:mm:ss").format(new Date()),f));
ct.go();
File src= ((TakesScreenshot)oDriver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(src, new
File(sSVNfolderPath+"\\Log_Files\\Snapshots\\Test.jpg"));
FileInputStream pic = new
FileInputStream(sSVNfolderPath+"\\Log_Files\\Snapshots\\Test.jpg");
InputStream is = new BufferedInputStream(pic);
java.awt.Image image = ImageIO.read(is);
Image img = Image.getInstance(image,null);
img.scalePercent(x);
img.setAbsolutePosition(x, y);
content.addImage(img);
pdfStamper.close();
pdfReader.close();
new File(sScreenShotFileName).delete();
new File(tempfile).renameTo(new File(sScreenShotFileName));
y=y*2;//setting y position to upward every time where the new image can be placed.
Thanks,
Meenal
I need to copy whole AcroForm including field positions and values from template PDF to a new blank PDF file. How can I do that?
In short words - I need to get rid of "background" from the template and leave only filed forms.
The whole point of this is to create a PDF with content that would be printed on pre-printed templates.
I am using IText 5 but I can switch to 7 if usefull examples would be provided
After a lot of trial and error I have found the solution to "How to copy AcfroForm fields into another PDF". It is a iText v7 version. I hope it will help somebody someday.
private byte[] copyFormElements(byte[] sourceTemplate) throws IOException {
PdfReader completeReader = new PdfReader(new ByteArrayInputStream(sourceTemplate));
PdfDocument completeDoc = new PdfDocument(completeReader);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PdfWriter offsetWriter = new PdfWriter(out);
PdfDocument offsetDoc = new PdfDocument(offsetWriter);
offsetDoc.initializeOutlines();
PdfPage blank = offsetDoc.addNewPage();
PdfAcroForm originalForm = PdfAcroForm.getAcroForm(completeDoc, false);
// originalForm.getPdfObject().copyTo(offsetDoc,false);
PdfAcroForm offsetForm = PdfAcroForm.getAcroForm(offsetDoc, true);
for (String name : originalForm.getFormFields().keySet()) {
PdfFormField field = originalForm.getField(name);
PdfDictionary copied = field.getPdfObject().copyTo(offsetDoc, false);
PdfFormField copiedField = PdfFormField.makeFormField(copied, offsetDoc);
offsetForm.addField(copiedField, blank);
}
offsetDoc.close();
completeDoc.close();
return out.toByteArray();
}
Did you check the PdfCopyForms object:
Allows you to add one (or more) existing PDF document(s) to create a new PDF and add the form of another PDF document to this new PDF.
I didn't find an example, but you could try something like this:
PdfReader reader1 = new PdfReader(src1); // a document with a form
PdfReader reader2 = new PdfReader(src2); // a document without a form
PdfCopyForms copy = new PdfCopyForms(new FileOutputStream(dest));
copy.AddDocument(reader1); // add the document without the form
copy.CopyDocumentFields(reader2); // add the fields of the document with the form
copy.close();
reader1.close();
reader2.close();
I see that the class is deprecated. I'm not sure of that's because iText 7 makes it much easier to do this, or if it's because there were technical problems with the class.
I want to create a new pdf for each iteration of the loop so i wrote the below code in java:
PdfWriter writer;
PdfDocument pdf;
Document document;
int i=0;
while(condition){
writer = new PdfWriter("test_"+Integer.toString(i)+".pdf");
pdf = new PdfDocument(writer);
document = new Document(pdf);
//content code here
document.close()
i++;
}
i get the below exception on the line of the document.close() command:
Exception in thread "main" com.itextpdf.kernel.PdfException: Pdf
indirect object belongs to other PDF document. Copy object to current
pdf document. at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:184)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:174)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:104)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:176)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:104)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:176)
at
com.itextpdf.kernel.pdf.PdfOutputStream.write(PdfOutputStream.java:104)
at com.itextpdf.kernel.pdf.PdfWriter.writeToBody(PdfWriter.java:335)
at com.itextpdf.kernel.pdf.PdfWriter.flushObject(PdfWriter.java:243)
at
com.itextpdf.kernel.pdf.PdfDocument.flushObject(PdfDocument.java:1446)
at com.itextpdf.kernel.pdf.PdfObject.flush(PdfObject.java:155) at
com.itextpdf.kernel.pdf.PdfObject.flush(PdfObject.java:128) at
com.itextpdf.kernel.pdf.PdfObjectWrapper.flush(PdfObjectWrapper.java:96)
at com.itextpdf.kernel.pdf.PdfPage.flush(PdfPage.java:489) at
com.itextpdf.kernel.pdf.PdfPage.flush(PdfPage.java:448) at
com.itextpdf.kernel.pdf.PdfDocument.close(PdfDocument.java:739) at
com.itextpdf.layout.Document.close(Document.java:120) at
gr.moh.Pdf.main(Pdf.java:224)
i have tried a lot but i cannot find why i get an error. If i do it without a loop it works. Any help?
P.S: i use itext 7
I had the below code out of the loop and it should be into the loop...
PdfFont normalFont = PdfFontFactory.createFont(fontDirectory.getAbsolutePath()+"\\arial.ttf", "Identity-H", true);
normal.setFont(normalFont).setFontSize(14);
Style red = new Style();
PdfFont redFont = PdfFontFactory.createFont(fontDirectory.getAbsolutePath()+"\\arial.ttf", "Identity-H", true);
red.setFont(redFont).setFontSize(14).setFontColor(Color.RED);
Style big = new Style();
PdfFont bigFont = PdfFontFactory.createFont(fontDirectory.getAbsolutePath()+"\\arial.ttf", "Identity-H", true);
big.setFont(bigFont).setFontSize(18).setBold();