简体   繁体   中英

PDFBox - Delete image from the page and add same image on different position

I am using PDFBox 2.x version and need to reposition the existing image from the page. For that, I'm removing the image from the page and adding it back again. But with my current implementation, it is not showing either image.

Please help me with this and let me know where I'm going wrong.

try {
  PDDocument document = PDDocument.load(new File("..\\sampleWithImage_with_barcode_img.pdf"));

  PDDocument newDocument = new PDDocument();
  for (int i = 0; i < document.getNumberOfPages(); i++) {
    PDPage sourcePage = document.getPage(i);
    PDPage pdPage = newDocument.importPage(sourcePage);
    pdPage.setResources(sourcePage.getResources());

    //To remove existing from the page
    stripUnusedImages(pdPage, newDocument);

    //ADD OTHER IMAGE
    PDImageXObject pdImage = PDImageXObject.createFromFile("D:\\copy\\pic.jpg", newDocument);

    PDPageContentStream contents = new PDPageContentStream(newDocument, pdPage,
      PDPageContentStream.AppendMode.APPEND, true);

    // Drawing the image in the PDF document
    contents.drawImage(pdImage, 0, 0, 50, 30);

    System.out.println("Image inserted Successfully.");

    // Closing the PDPageContentStream object
    contents.close();
  }
  newDocument.save("..\\RemovedImage.pdf");
  document.close();
  newDocument.close();

} catch (Exception e) {
  e.printStackTrace();
}

//Method to remove image
protected void stripUnusedImages(PDPage page, PDDocument document) throws IOException, XmpParsingException {
  PDResources resources = copyResources(page);
  PDFStreamParser parser = new PDFStreamParser(page);
  parser.parse();

  List < Object > tokens = parser.getTokens();
  System.out.println("Total Tokens=" + tokens.size());
  List < Object > newTokens = new ArrayList < Object > ();
  for (int j = 0; j < tokens.size(); j++) {
    Object token = tokens.get(j);
    if (token instanceof COSName) {
      COSName cosname = (COSName) token;
      PDXObject o = resources.getXObject(cosname);
      if (o instanceof PDImageXObject) {
        PDImageXObject pdImageXObject = (PDImageXObject) o;
        if (pdImageXObject.getMetadata() != null) {
          System.out.println("pdImageXObjec metadata exist");
          newTokens.remove(newTokens.size() - 1);
          continue;
        }
      }
    }

    newTokens.add(token);
  }

  PDStream newContents = new PDStream(document);
  OutputStream outputStream = newContents.createOutputStream();
  ContentStreamWriter writer = new ContentStreamWriter(outputStream);
  writer.writeTokens(newTokens);
  outputStream.close();
  newContents.addCompression();
  page.setContents(newContents);
}

The PDPageContentStream is constructed like this:

PDPageContentStream contents = new PDPageContentStream(newDocument, pdPage,
  PDPageContentStream.AppendMode.APPEND, true);

Tilman Hausherr in a comment proposed adding a fifth "true" parameter :

PDPageContentStream contents = new PDPageContentStream(newDocument, pdPage,
  PDPageContentStream.AppendMode.APPEND, true, true);

This causes the previously existing page content to be enveloped in a save-graphics-state/restore-graphics-state frame which resets the graphics state at the end to the original one to prevent changes in particular to the current transformation matrix from influencing one's new additions.

Ronak additionally according to a comment per his requirement changed AppendMode from APPEND to PREPEND in 3rd param value. This causes his changes to be added in the background, not the foreground.

So the final version of the PDPageContentStream construction is this:

PDPageContentStream contents = new PDPageContentStream(newDocument, pdPage,
  PDPageContentStream.AppendMode.PREPEND, true, true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM