在 PDFBox 2.0 中使用覆盖

Using Overlay in PDFBox 2.0

我在这里要做的是创建文本并将其放在空白页上。然后该页面将覆盖在另一个文档上,然后将其保存为一个文档。在 1.8 中,我能够在 PDF 中创建一个空白的 PDPage,根据需要向其中写入文本,然后用另一个 PDF 覆盖该 PDF,然后使用以下代码在屏幕上保存或查看 -

overlayDoc = new PDDocument();
page = new PDPage();
overlayDoc.addPage(page);
overlayObj = new Overlay();
font = PDType1Font.COURIER_OBLIQUE;
try {
    contentStream = new PDPageContentStream(overlayDoc, page);
    contentStream.setFont(font, 10);
}
catch (Exception e){
    System.out.println("content stream failed");
}

创建流后,当我需要向覆盖文档的 contentStream 写入内容时,我会调用此方法,为其提供我的 x、y 坐标并告诉它要写入的文本(同样,这是在我的1.8 版本):

protected void writeString(int x, int y, String text) {
    if (text == null) return;
    try {
        contentStream.moveTo(x, y);
        contentStream.beginText();
        contentStream.drawString(text);  // deprecated. Use showText(String text)
        contentStream.endText();
    }
    catch (Exception e){
        System.out.println(text + " failed. " + e.toString());
    }
}

每当我需要添加文本时,我都会调用这个方法,无论我需要添加到哪里。在此之后,我将关闭我的内容流,然后将文档合并在一起:

import org.apache.pdfbox.Overlay;
Overlay overlayObj = new Overlay();

....

PDDocument finalDoc = overlayObj.overlay(overlayDoc, originalDoc);

finalDoc 现在包含一个 PDDocument,它是我的原始 PDF,在需要的地方覆盖了文本。我可以保存它并将其作为 BufferedImage 在桌面上查看。我转向 2.0 的原因是,首先我需要保持在最新库的顶部,而且我在将图像放到页面上时遇到了问题(参见 here)。

我在这个问题中遇到的问题是 2.0 不再具有类似于 org.apache.pdfbox.Overlay class 的内容。更让我困惑的是 1.8 中有两个 Overlay classes (org.apache.pdfbox.Overlay and org.apache.pdfbox.util.Overlay) whereas in 2.0 there is only one. The class I need (org.apache.pdfbox.Overlay), or the methods it offers at least, are not present in 2.0 as far as I can tell. I can only find org.apache.pdfbox.multipdf.Overlay.

这是一些有效的快速代码,它在文档上添加 "deprecated" 并将其保存在其他地方:

    PDDocument overlayDoc = new PDDocument();
    PDPage page = new PDPage();
    overlayDoc.addPage(page);
    Overlay overlayObj = new Overlay();
    PDFont font = PDType1Font.COURIER_OBLIQUE;

    PDPageContentStream contentStream = new PDPageContentStream(overlayDoc, page);
    contentStream.setFont(font, 50);
    contentStream.setNonStrokingColor(0);
    contentStream.beginText();
    contentStream.moveTextPositionByAmount(200, 200);
    contentStream.drawString("deprecated");  // deprecated. Use showText(String text)
    contentStream.endText();
    contentStream.close();

    PDDocument originalDoc = PDDocument.load(new File("...inputfile.pdf"));
    overlayObj.setOverlayPosition(Overlay.Position.FOREGROUND);
    overlayObj.setInputPDF(originalDoc);
    overlayObj.setAllPagesOverlayPDF(overlayDoc);
    Map<Integer, String> ovmap = new HashMap<Integer, String>(); // empty map is a dummy
    overlayObj.setOutputFile("... result-with-overlay.pdf");
    overlayObj.overlay(ovmap);
    overlayDoc.close();
    originalDoc.close();

我对你的版本做了什么:

  • 声明变量
  • 关闭内容流
  • 设置颜色
  • 设为前景
  • 设置文字位置(不是笔划路径位置)
  • 添加一张空地图

当然,我阅读了 OverlayPDF source code,它展示了使用 class 可以做的更多可能性。

奖励内容:

在不使用覆盖 class 的情况下执行相同的操作,这允许在保存文档之前进一步操作它。

    PDFont font = PDType1Font.COURIER_OBLIQUE;
    PDDocument originalDoc = PDDocument.load(new File("...inputfile.pdf"));
    PDPage page1 = originalDoc.getPage(0);
    PDPageContentStream contentStream = new PDPageContentStream(originalDoc, page1, true, true, true);
    contentStream.setFont(font, 50);
    contentStream.setNonStrokingColor(0);
    contentStream.beginText();
    contentStream.moveTextPositionByAmount(200, 200);
    contentStream.drawString("deprecated");  // deprecated. Use showText(String text)
    contentStream.endText();
    contentStream.close();
    originalDoc.save("....result2.pdf");
    originalDoc.close();