PDFBox叠加失败

时间:2015-03-17 09:45:10

标签: overlay pdfbox

我使用PDFBox 1.8.8并尝试使用以下scala方法将PDDocument与其他文档重叠

def mergeTest() = {
val home = System.getProperty("user.home")
val doc = PDDocument.load(home + "/tmp/document.pdf")
val ovl = PDDocument.load(home + "/tmp/overlay.pdf")
val ov = new Overlay()
val mergeDoc = ov.overlay(ovl, doc)
mergeDoc.save(home + "/tmp/result.pdf")
doc.close()
ovl.close()
mergeDoc.close()

}

我原本期望将“document.pdf”(N页)的每一页都覆盖“overlay.pdf”(1页)的内容。

“result.pdf”中的结果与“document.pdf”中的页数一样多,但“document.pdf”的原始内容完全被覆盖的内容覆盖。

1 个答案:

答案 0 :(得分:2)

原因

OP的overlay.pdf页面内容以

开头
/Cs1 cs
1 sc
0.1400146 841.945 m
595.14 841.945 l
595.14 -0.05499268 l
0.1400146 -0.05499268 l
h
f
0.1400146 841.945 m
595.14 841.945 l
595.14 -0.05499268 l
0.1400146 -0.05499268 l
h
f

这些操作绘制了两个白色( CS1 是一个灰度色彩空间)矩形,几乎覆盖了整个 MediaBox [0, 0, 595.28, 841.89],除了非常纤细的线条顶部和左侧

因此,将此页面内容放在另一个页面上,完全覆盖了其他页面的所有现有内容,这正是您所观察到的内容:

  

“document.pdf”的原始内容被覆盖的内容完全覆盖

通常只有覆盖一个不包含所有内容的页面才有意义。

使用混合模式变暗

的变通方法

或者,你可能想尝试使用混合模式覆盖变暗,其中选择较暗的背景和源颜色将背景替换为源光源较暗的地方;否则,它保持不变。

在Java中(我没有使用Scala的经验,所以我希望你可以使用Java源码)你可以使用这样的方法:

void overlayWithDarkenBlendMode(PDDocument document, PDDocument overlay) throws IOException
{
    PDXObjectForm xobject = importAsXObject(document, (PDPage) overlay.getDocumentCatalog().getAllPages().get(0));
    PDExtendedGraphicsState darken = new PDExtendedGraphicsState();
    darken.getCOSDictionary().setName("BM", "Darken");

    List<PDPage> pages = document.getDocumentCatalog().getAllPages();

    for (PDPage page: pages)
    {
        Map<String, PDExtendedGraphicsState> states = page.getResources().getGraphicsStates();
        if (states == null)
            states = new HashMap<String, PDExtendedGraphicsState>();
        String darkenKey = MapUtil.getNextUniqueKey(states, "Dkn");
        states.put(darkenKey, darken);
        page.getResources().setGraphicsStates(states);

        PDPageContentStream stream = new PDPageContentStream(document, page, true, false, true);
        stream.appendRawCommands(String.format("/%s gs ", darkenKey));
        stream.drawXObject(xobject, 0, 0, 1, 1);
        stream.close();
    }
}

PDXObjectForm importAsXObject(PDDocument target, PDPage page) throws IOException
{
    final PDStream xobjectStream = new PDStream(target, page.getContents().createInputStream(), false);
    final PDXObjectForm xobject = new PDXObjectForm(xobjectStream);

    xobject.setResources(page.findResources());
    xobject.setBBox(page.findCropBox());

    COSDictionary group = new COSDictionary();
    group.setName("S", "Transparency");
    group.setBoolean(COSName.getPDFName("K"), true);
    xobject.getCOSStream().setItem(COSName.getPDFName("Group"), group);

    return xobject;
}
     

OverlayWithEffect.java

将它们应用于您的样本文件

@Test
public void testOverlayWithDarkenVolker() throws COSVisitorException, IOException
{
    try (   InputStream sourceStream = getClass().getResourceAsStream("document1.pdf");
            InputStream overlayStream = getClass().getResourceAsStream("overlay.pdf")  )
    {
        final PDDocument document = PDDocument.load(sourceStream);
        final PDDocument overlay = PDDocument.load(overlayStream);

        overlayWithDarkenBlendMode(document, overlay);

        document.save(new File(RESULT_FOLDER, "document1-with-overlay.pdf"));
    }
}

结果

document1-with-overlay.pdf

如您所见,来自document1.pdf的数字和来自overlay.pdf的数字都在那里。

小心! 此代码是概念验证,尚未准备好用于一般生产用途。它例如完全忽略旋转页面条目......