【问题标题】:PDF issue with fonts in adobe, after using overlays in PDFBox在 PDFBox 中使用叠加层后,Adobe 中的字体出现 PDF 问题
【发布时间】:2021-02-09 16:20:49
【问题描述】:

我们在其中一个应用程序中使用 pdfbox。 一些重叠的 pdf 会导致“损坏”的输出和字体。

下面是我用来覆盖 pdf 的示例代码。 pdf有时有不同的页数。 我们将 acroform 展平并将注释设置为只读。 Pdf 页面旋转和 bbox 大小有时设置不同(尤其是扫描仪),因此我们尝试对此进行更正。

    PDDocument baseDocument = PDDocument.load(new File("base.pdf"));
    PDDocument overlayDocument = PDDocument.load(new File("overlay.pdf"));
    Iterator<PDPage> baseDocumentIterator = baseDocument.getPages().iterator();
    Iterator<PDPage> overlayIterator = overlayDocument.getPages().iterator();
    PDDocument finalOverlayDoc = new PDDocument();
    while(baseDocumentIterator.hasNext() && overlayIterator.hasNext()) {
        PDPage backing = baseDocumentIterator.next();
        //locking annotations per page
        List<PDAnnotation> annotations = backing.getAnnotations();
        for (PDAnnotation a :annotations) {
            a.setLocked(true);
            a.setReadOnly(true);
        }
        // setting size so there's no weird overflow issues
        PDRectangle rect = new PDRectangle();
        rect.setLowerLeftX(0);
        rect.setLowerLeftY(0);
        rect.setUpperRightX(backing.getBBox().getWidth());
        rect.setUpperRightY(backing.getBBox().getHeight());
        backing.setCropBox(rect);
        backing.setMediaBox(rect);
        backing.setBleedBox(rect);
        PDPage pg = overlayIterator.next();
        //setting rotation if different. Some scanners cause issues.
        if(backing.getRotation()!= pg.getRotation())
        {
            pg.setRotation(-backing.getRotation());
        }
        finalOverlayDoc.addPage(pg);
    }
    finalOverlayDoc.close();
    //flatten acroform
    PDAcroForm acroForm = baseDocument.getDocumentCatalog().getAcroForm();
    if (acroForm != null) {
        acroForm.flatten();
        acroForm.setNeedAppearances(false);
    }
    Overlay overlay = new Overlay();
    overlay.setOverlayPosition(Overlay.Position.FOREGROUND);
    overlay.setInputPDF(baseDocument);
    overlay.setAllPagesOverlayPDF(finalOverlayDoc);

    Map<Integer, String> ovmap = new HashMap<Integer, String>();
    overlay.overlay(ovmap);
    PDPageTree allOverlayPages = overlayDocument.getPages();
    if(baseDocument.getPages().getCount() < overlayDocument.getPages().getCount()) //Additional pages in the overlay pdf need to be appended to the base pdf.
    {
        for(int i=baseDocument.getPages().getCount();i<allOverlayPages.getCount(); i++)
        {
            baseDocument.addPage(allOverlayPages.get(i));
        }
    }
    PDDocument finalDocument = new PDDocument();
    for(PDPage p: baseDocument.getPages()){
        finalDocument.addPage(p);
    }

    String filename = "examples/merge_pdf_examples/debug.pdf";
    filename = filename + new Date().getTime() + ".pdf";
    finalDocument.save(filename);
    finalDocument.close();
    baseDocument.close();
    overlayDocument.close();

【问题讨论】:

  • 请准确说明您希望能够修复哪些错误。
  • @mkl,谢谢。我现在看到 Preflight 会返回大量关于 pdf 的不同问题。我添加了 3 个有问题的 pdf 的详细信息。我们正在使用 pdfbox 中的 overlay(),将我们的 pdf 覆盖在有问题的 pdf 之上。大多数情况下,这可以完美运行,只有少数情况下我们会遇到上述问题。在覆盖之前使用 pdfbox 的 prepress 是否可以解决这些问题?
  • 您显示的错误似乎与 PDF/A 相关,一般与 PDF 无关。这真的是你的意思吗?您的问题最初听起来像是您的意思是一般的 PDF 错误。
  • @mkl,谢谢。直到你提到它,我才意识到这些差异。所以听起来我使用预检错误或根本不应该使用预检。问题是我不知道原始 pdf 有什么问题,只是这些“错误”的 pdf 在与叠加层合并时无法在 adobe 中打开并且文本变成乱码。
  • 根据您的 PreflightParser 链接:Apache Preflight 库是一种 Java 工具,可实现符合 ISO-19005 规范(又名 PDF/A-1)的解析器。 所以恐怕不是用于通用 PDF 验证,仅用于特定 PDF/A-1 验证。

标签: java pdf pdfbox


【解决方案1】:

您分享的与使用 Overlay 相关的 PDF 文件中没有错误。

它使用了一个很少使用的 PDF 功能,但是,页面 继承 来自其父节点的资源: PDF 中的页面对象排列在树中,实际页面是叶子;这棵树中的页面对象通常本身携带定义它的所有信息,但许多页面属性也可以由内部节点携带并由后代页面继承,除非它们覆盖它们。

在您分享您的代码后,事实证明您有一个准备步骤会丢失所有继承的信息:当您从 overlayDocument 生成 finalOverlayDoc 时,您实际上是这样做的:

while(overlayIterator.hasNext()) {
    PDPage pg = overlayIterator.next();
    //setting rotation if different. Some scanners cause issues.
    finalOverlayDoc.addPage(pg);
}

(OverlayDocuments 测试testOverlayPreparationExampleBroken)

这里你只传输页面对象本身,丢失所有继承的属性。

对于手头的文档,您可以通过将页面资源显式设置为继承的资源来解决此问题:

while(overlayIterator.hasNext()) {
    PDPage pg = overlayIterator.next();
    pg.setResources(pg.getResources());
    //setting rotation if different. Some scanners cause issues.
    finalOverlayDoc.addPage(pg);
}

(OverlayDocuments 测试testOverlayPreparationFixedExampleBroken)

但请注意:这只是显式设置页面资源,但还有其他页面属性可以继承。

因此,我建议您根本不要创建新的PDDocument;而不是将overlayDocument 页面移动到finalOverlayDoc 只需将它们更改到位。如果overlayDocument 的页面比baseDocument 多,您还必须从overlayDocument 中删除多余的页面。然后在覆盖中使用overlayDocument 而不是finalOverlayDoc


进一步查看您的代码,我看到您重复将页面对象移动到其他文档的反模式,而一次又一次地不尊重继承的属性。我想你应该彻底检查那个代码,去掉那个反模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-16
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多