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
Related
I have a springBoot project and i am trying to insert an image into PDF using PDFBox library. The image is present in src/main/resources/image folder (myImage.jpg). The implementation code is as given below. While running the program i am getting an error that image is not found at specified path. What is the correct way to retrieve the image from classpath in this scenario.
public class PDFImageService {
public void insertImage() throws IOException {
//Loading an existing document
File file = new File("/eclipse-workspace/blank.pdf");
PDDocument doc = PDDocument.load(file);
//Retrieving the page
PDPage page = doc.getPage(1);
//Creating PDImageXObject object
PDImageXObject pdImage = PDImageXObject.createFromFile("/image/myImage.jpg",doc);
//creating the PDPageContentStream object
PDPageContentStream contents = new PDPageContentStream(doc, page);
//Drawing the image in the PDF document
contents.drawImage(pdImage, 250, 300);
System.out.println("Image inserted Successfully.");
//Closing the PDPageContentStream object
contents.close();
//Saving the document
doc.save("/eclipse-workspace/blank.pdf");
//Closing the document
doc.close();
}
}
It works fine if i give the fully specified image path as
PDImageXObject pdImage = PDImageXObject.createFromFile("C:\Users\Dell\Desktop\PDF\myImage.jpg",doc);
As discussed in the comments, it works by using
PDImageXObject img;
try (InputStream is = PDFImageService.class.getResourceAsStream("/image/myImage.jpg");
{
// check whether InputStream is null omitted
byte [] ba = IOUtils.toByteArray(imageAsStream);
img = PDImageXObject.createFromByteArray(document, ba, "myImage.jpg");
}
Unless eclipse-workspace folder is on / (root) the top file in the OS then it would be implicit and incorrectly stated, when you installed configured eclipse it usually asserts the user home folder to put workspace into. If it is on root / then i suggest you add a FileNotFoundException before the IOException.
This question already has answers here:
Problem with empty page when using Apache PDFBox to add image to PDF
(1 answer)
Edit pdf page using pdfbox
(3 answers)
Opening a content stream blanks saved content?
(2 answers)
PdfBox adding multiple images into pdf
(1 answer)
Table disappears when drawn before contentStream - PDFBox with Boxable
(1 answer)
Closed 4 years ago.
I want to highlight a perticular text in the pdf.I have writen the following code but i am getting empty pdf with the box.I want to show the existing pdf content and the box should be drawn on the text so it will act as a text highliter.
File file = new File(pdfName);
PDDocument document = PDDocument.load(file);
PDPage page = document.getPage(0);
//Instantiating the PDPageContentStream class
PDPageContentStream contentStream = new PDPageContentStream(document, page);
//Setting the non stroking color
contentStream.setNonStrokingColor(Color.DARK_GRAY);
//Drawing a rectangle
contentStream.addRect(data.get(0).getX(), data.get(0).getY(), data.get(0).getWidth(), data.get(0).getHeight());
//Drawing a rectangle
contentStream.fill();
System.out.println("rectangle added");
//Closing the ContentStream object
contentStream.close();
//Saving the document
//File file2 = new File("CompareOutput.pdf");
//File fileOutput = new File("CompareOutput.pdf");
document.save("CompareOutput.pdf");
//Closing the document
document.close();
Instead of
PDPageContentStream contentStream = new PDPageContentStream(document, page);
use
PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true, true))
This way your new content stream is appended.
However I expect another problem, you may want the "highlight" to be transparent. Have a look at this answer.
I am using PdfBox to generate pdf with an existing Pdf containing the template which has to be used for every Pdf that i want to generate.
But When i try to load the template pdf and wants to write something in it, all previous contains were removed.
So i want both the content should be shown.
Please suggest any solution for it.
Here is the code i am trying to do :
//Loading an existing document
File file = new File("/home/spaneos/ScoringReports-TM-110617.pdf");
PDDocument document = PDDocument.load(file);
//Retrieving the pages of the document
PDPage page = document.getPage(0);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
//Begin the Content stream
contentStream.beginText();
//Setting the font to the Content stream
contentStream.setFont( PDType1Font.TIMES_ROMAN, 16 );
//Setting the leading
contentStream.setLeading(14.5f);
//Setting the position for the line
contentStream.newLineAtOffset(25, 725);
String text1 = "This is an example of adding text to a page in the pdf document.we can add as many lines";
String text2 = "as we want like this using the ShowText() method of the ContentStream class";
//Adding text in the form of string
contentStream.showText(text1);
contentStream.newLine();
contentStream.showText(text2);
//Creating PDImageXObject object
PDImageXObject pdImage = PDImageXObject.createFromFile("/home/spaneos/Downloads/man-161282_960_720.png",document);
//creating the PDPageContentStream object
PDPageContentStream contents = new PDPageContentStream(document, page);
contentStream.endText();
System.out.println("Content added");
//Closing the PDPageContentStream object
contents.close();
//Closing the content stream
contentStream.close();
//Saving the document
document.save(System.getProperty("user.dir").concat("/PdfBox_Examples/sample.pdf"));
//Closing the document
document.close();
You create the PDPageContentStream instances like this
PDPageContentStream contentStream = new PDPageContentStream(document, page);
[...]
PDPageContentStream contents = new PDPageContentStream(document, page);
Creating it using this constructor replaces any existing content streams with the new one. Instead use this one:
PDPageContentStream contents = new PDPageContentStream(document, page, AppendMode.APPEND, true, true);
AppendMode.APPEND here tells PDFBox to append the new stream, the first true tells it to compress the stream, and the second true tells it to reset the graphics state at the start of your added stream.
Furthermore, you don't really use the second content stream...
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.
I am trying to dynamically add PDF pages depending upon content size.
for that I did not want to clutter the main method, instead I created a separate method to write the PDF and call the method from main() like below:
//PDF Log Method
PDlog("Create First Page", "b");
PDlog("add more page", "b");
PDlog("close pdf", "b");
I have added system.out.println at the end of each if condition, and all three are getting printed on IDE screen. but an Empty PDF is being generated after 3 method calls end. When I had only one if condition and called the PDlog method only once, the PDF is being saved and closed properly.
How can I call this method multiple times from main and keep on adding page and content multiple times?
Below is the method code:
public static void PDlog(String action, String msg) throws IOException, ClassNotFoundException, SQLException, InterruptedException, COSVisitorException {
//Master PDF Log File --------------------------------------------------------------------
String masterPDLog = "X:\\eHub\\QA\\eHub_Automation_Log.pdf";
// Create a document and add a page to it
PDDocument document = new PDDocument();
PDPage page = new PDPage(PDPage.PAGE_SIZE_A4);
if (action.equals("Create First Page")) {
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.TIMES_ROMAN;
PDFont boldFont = PDType1Font.TIMES_BOLD;
//File for CTS Logo --------------------
InputStream in = new FileInputStream(new File("X:\\eHub\\QA\\img\\cts.jpg"));
PDJpeg img = new PDJpeg(document, in);
// Start a new content stream which will "hold" the to be created content
PDPageContentStream contentStream = new PDPageContentStream(document, page);
//Place CTS Logo
//contentStream.drawImage(img, 500, 750);
contentStream.drawXObject( img, 450, 700, 50, 50 );
// Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
contentStream.beginText();
contentStream.setFont( boldFont, 20 );
contentStream.setNonStrokingColor(Color.BLUE);
contentStream.moveTextPositionByAmount( 120, 650 );
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.beginText();
contentStream.setFont( boldFont, 20 );
contentStream.setNonStrokingColor(Color.BLUE);
contentStream.moveTextPositionByAmount( 140, 600 );
contentStream.drawString("Data Profiling/Quality/Analysis");
contentStream.endText();
// Make sure that the content stream is closed:
contentStream.close();
//document.save(masterPDLog);
System.out.println("1ST PAGE ADDED");
}
else if (action.equals("add more page")) {
PDFont font = PDType1Font.TIMES_ROMAN;
document.addPage(page);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont( font, 20 );
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.moveTextPositionByAmount( 100, 800 );
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.close();
//document.save(masterPDLog);
System.out.println("2ND PAGE ADDED");
}
else if (action.equals("close pdf")) {
PDFont font = PDType1Font.TIMES_ROMAN;
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont( font, 20 );
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.moveTextPositionByAmount( 100, 800 );
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.close();
document.save(masterPDLog);
document.close();
System.out.println("PDF CLOSED");
}
You create the document each time, that is why.
Just pass the document object to your method, and create the document first - here's your code, corrected:
public static void main(String[] args) throws IOException, COSVisitorException
{
PDDocument document = new PDDocument();
pdlog("Create First Page", "b", document);
pdlog("add more page", "b", document);
pdlog("close pdf", "b", document);
}
public static void pdlog(String action, String msg, PDDocument document) throws IOException, COSVisitorException
{
//Master PDF Log File --------------------------------------------------------------------
String masterPDLog = "X:\\eHub\\QA\\eHub_Automation_Log.pdf";
// Create a document and add a page to it
PDPage page = new PDPage(PDPage.PAGE_SIZE_A4);
if (action.equals("Create First Page"))
{
document.addPage(page);
// Create a new font object selecting one of the PDF base fonts
PDFont font = PDType1Font.TIMES_ROMAN;
PDFont boldFont = PDType1Font.TIMES_BOLD;
//File for CTS Logo --------------------
InputStream in = new FileInputStream(new File("X:\\eHub\\QA\\img\\cts.jpg"));
PDJpeg img = new PDJpeg(document, in);
// Start a new content stream which will "hold" the to be created content
PDPageContentStream contentStream = new PDPageContentStream(document, page);
//Place CTS Logo
//contentStream.drawImage(img, 500, 750);
contentStream.drawXObject(img, 450, 700, 50, 50);
// Define a text content stream using the selected font, moving the cursor and drawing the text "Hello World"
contentStream.beginText();
contentStream.setFont(boldFont, 20);
contentStream.setNonStrokingColor(Color.BLUE);
contentStream.moveTextPositionByAmount(120, 650);
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.beginText();
contentStream.setFont(boldFont, 20);
contentStream.setNonStrokingColor(Color.BLUE);
contentStream.moveTextPositionByAmount(140, 600);
contentStream.drawString("Data Profiling/Quality/Analysis");
contentStream.endText();
// Make sure that the content stream is closed:
contentStream.close();
//document.save(masterPDLog);
System.out.println("1ST PAGE ADDED");
}
else if (action.equals("add more page"))
{
PDFont font = PDType1Font.TIMES_ROMAN;
document.addPage(page);
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.moveTextPositionByAmount(100, 800);
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.close();
//document.save(masterPDLog);
System.out.println("2ND PAGE ADDED");
}
else if (action.equals("close pdf"))
{
PDFont font = PDType1Font.TIMES_ROMAN;
PDPageContentStream contentStream = new PDPageContentStream(document, page);
contentStream.beginText();
contentStream.setFont(font, 20);
contentStream.setNonStrokingColor(Color.BLACK);
contentStream.moveTextPositionByAmount(100, 800);
contentStream.drawString("eHub Automated Data Quality Report");
contentStream.endText();
contentStream.close();
document.save(masterPDLog);
document.close();
System.out.println("PDF CLOSED");
}
}
Your "close pdf" action does not make much sense, you are writing to a PDPage that is never appended.
1st of all, thanks Tilman for answering my actual question.
In the meantime, for practical purposes, I have changed my approach to writing dynamically to a PDF, as the code flows through If Else and Loops.... instead I have chosen to simply keep on Logging to simple text file using PrintWriter.
At the final end of the code, I am calling a method to Read each line of the Text Log file and place in a PDF document. To Summarize: One time Text to PDF conversion.
I explored iText and chose it over Apache PDFBox, it is perhaps 2-3 times faster than PDFBox and adding page is implicit and automatic.