Search code examples
itextitext7

iText - add image to an existing PDF


I am doing the following using iText.

  1. I have a PDF
  2. I add an image to the PDF
  3. I save the modified PDF.

To add image in PDF I am using this method itext-add. This worked fine until I got a certain PDF. In this PDF, the adding-image-to-the-pdf method doesn't work. Moreover, it corrupts the PDF.

Points to note: I'm getting PDFs from a third party and these are contractual PDFs. So it is possible that they have added some restrictions.

And one fun fact, when I add an annotation on the same page where I want to add that image, that image starts coming!

I'm using iText 7.1.10

    String srcFileName = "/Users/kalpit/Desktop/step1-stack.pdf";
    String destFileName = "step1-test1-kd2.pdf";

    File destFile = new File(destFileName);
    PdfDocument pdf = new PdfDocument(new PdfReader(srcFileName), new PdfWriter(destFile),new StampingProperties().useAppendMode());

    Document document = new Document(pdf);

    String imFile = "/Users/kalpit/Desktop/sample-image.png";
    ImageData data = ImageDataFactory.create(imFile);

    Image image = new Image(data);
    document.add(image);

    document.close();

and here is the PDF : https://ipupload.com/tP6/step1.pdf


Solution

  • As @Nikita found out, the problem does only occur if working in append mode. The cause is that in unfortunate conditions the changed resources are not stored, a bug.

    The unfortunate conditions here are that on page 1

    • the content stream array already is an indirect object in its own right, so only this indirect object (and not the page object) is marked as changed when the instructions for showing the image are added; and
    • the resources and resource type dictionaries are direct objects but only they (and not the page object, the indirect object holding them) are marked as changed when the image resource is added.

    Thus, the changes to the page content streams are stored but the page object is not. So there now is an instruction to draw an image from an image page resource which is not there.

    One way to work around this is not to use append mode as proposed by @Nikita.

    Alternatively, if you are required to use append mode, you can explicitly mark your page as changed:

    Document document = new Document(pdf);
    
    String imFile = "/Users/kalpit/Desktop/sample-image.png";
    ImageData data = ImageDataFactory.create(imFile);
    
    Image image = new Image(data);
    document.add(image);
    
    pdf.getFirstPage().setModified(); // <-----
    
    document.close();