PDFBox-从页面删除图像并在不同位置添加相同图像

问题描述

我正在使用PDFBox 2.x版本,需要从页面重新定位现有图像。为此,我要从页面删除图像,然后再次添加回去。但是在我当前的实现中,它不会显示任何图像。

请帮助我,让我知道我要去哪里了。

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,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);
}

解决方法

PDPageContentStream的构造如下:

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

蒂尔曼·豪瑟(Tilman Hausherr)在评论中建议添加第五个“ true”参数

PDPageContentStream contents = new PDPageContentStream(newDocument,true,true);

这将导致先前存在的页面内容被封装在save-graphics-state / restore-graphics-state框架中,该框架将最后的图形状态重置为原始状态,以防止特别是对当前转换矩阵的更改。影响一个人的新事物。

Ronak还会根据评论根据他的要求,将第3个参数值中的AppendMode 从APPEND更改为PREPEND 这会使他的更改添加到后台,而不是前景。

所以PDPageContentStream结构的最终版本是这样的:

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