8
votes

I am using iText (specifically iTextSharp 4.1.6) and I want to create a PDF by combining pages from existing PDFs but also inserting new pages created from an image.

I have got these two parts working separately using PdfCopy and PdfWriter respectively. The code to create a page from an image looks like this:

PdfWriter pw = PdfWriter.GetInstance(doc, outputStream);
Image img = Image.GetInstance(inputStream);
doc.Add(img);
doc.NewPage();

Now, Since PdfCopy inherits from PdfWriter, I thought I would be able to add such "image pages" to my PdfCopy object using the same technique, but it doesn't work (if you instantiate a PdfCopy instead of a PdfWriter in the above example, nothing comes out on the page).

From a quick peek at the source code I notice that when the contstructor for PdfCopy calls the superclass constructor it does so with a new Document object, not the one passed in, so I guess this is the reason.

Is there a better way to go about this? At the moment my best guess is to create a single page Pdf from the image using PdfWriter and then add it to the document using PdfCopy, but that seems like a bit of a workaround.

2
What you described as a work around to me seems a proper solution. PdfCopy is designed to combine multiple PDFs, and you apply it to your previously existing pdfs and your newly create one. if the image is not too big, you can create that PDF in memory (byte[]) and read it from there; thus, there even is no need for additional temporary files. - mkl
Thanks - I'm not too familiar with iText and it seems so fully featured that I just wasn't sure if there was a whole other way of doing this. I have implemented it creating the temporary PDF in-memory and it all works lovely :-) - Andy

2 Answers

10
votes

I recently had this issue, and the answers here arent actually that helpful. My use-case was basically "Take a bunch of PDFs and images (.jpg, .png etc) and combine them all into 1 PDF". I had to use PdfCopy because it preserves things like form fields and labels, where PdfWriter doesnt.

Basically, because PdfCopy wont allow you to create new pages with addPage(), you have to create a new PDF in memory with the image on the page, and then use PdfCopy to copy out the page from that PDF.

For example:

    Document pdfDocument = new Document();
    ByteArrayOutputStream pdfOutputStream = new ByteArrayOutputStream();
    PdfCopy copy = new PdfCopy(pdfDocument, pdfOutputStream);

    pdfDocument.open();

    for (File file : allFiles) {
       if (/* file is PDF */) {
           /* Copy all the pages in the PDF file into the new PDF */
           PdfReader reader = new PdfReader(file.getAllBytes());
           for (int i = 1; i <= reader.getNumberOfPages(); i++) {
              copy.addPage(copy.getImportedPage(reader, i);
           }
       } else {
           /* File is image. Create a new PDF in memory, write the image to its first page, and then use PdfCopy to copy that first page back into the main PDF */
           Document imageDocument = new Document();
           ByteArrayOutputStream imageDocumentOutputStream = new ByteArrayOutputStream();
           PdfWriter imageDocumentWriter = PdfWriter.getInstance(imageDocument, imageDocumentOutputStream);

            imageDocument.open();

            if (imageDocument.newPage()) {

                image = Image.getInstance(file.getAllBytes());

                if (!imageDocument.add(image)) {
                   throw new Exception("Unable to add image to page!");
                }

                imageDocument.close();
                imageDocumentWriter.close();

                PdfReader imageDocumentReader = new PdfReader(imageDocumentOutputStream.toByteArray());

                copy.addPage(copy.getImportedPage(imageDocumentReader, 1));

                imageDocumentReader.close();
         }

     }
0
votes

You can add a page to a document (named copy in your example) created with PdfCopy with the syntax:

Rectangle rec = new Rectangle(10, 10, 10, 10);
copy.AddPage(rec, 1);