PDFBox叠加失败 [英] PDFBox Overlay fails

查看:213
本文介绍了PDFBox叠加失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I use PDFBox 1.8.8 and try to overlay a PDDocument with an other document by using the following scala method

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页)的内容.

I have expected to get every page of "document.pdf" (N pages) overlayed with the content of "overlay.pdf" (1 page).

结果是"result.pdf"中的页面与"document.pdf"中的页面一样多,但是"document.pdf"的原始内容被覆盖内容完全覆盖.

As a result in "result.pdf" there are as many pages as in "document.pdf", however the original content of "document.pdf" is completely overwritten by the content of the overlay.

推荐答案

原因

OP的 overlay.pdf 页面内容始于

The cause

The OP's overlay.pdf page content starts with

/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],但顶部的线条很细在左侧

These operations draw two white (CS1 is a grayscale color space) rectangles covering nearly the whole MediaBox [0, 0, 595.28, 841.89] with the exception of a very slim line at the top and at the left

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

Laying this page content over another page, therefore, completely covers all existing content of that other page which is exactly what you have observed:

"document.pdf"的原始内容被覆盖层的内容完全覆盖

the original content of "document.pdf" is completely overwritten by the content of the overlay

通常只覆盖不包含所有内容的页面是有意义的.

It usually only makes sense to overlay with a page which does not cover everything.

或者,您可能要尝试使用混合模式 Darken (重叠模式)进行叠加,该模式选择较暗的背景和源颜色将背景替换为源光源较暗的地方;否则,它保持不变.

Alternatively you might want to try overlaying using the blend mode Darken which selects the darker of the backdrop and source colours, the backdrop is replaced with the source where the source is darker; otherwise, it is left unchanged.

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

In Java (I have no experience with Scala, so I hope you can make use of Java source) you can use methods like these:

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.pdf 的两个数字以及 overlay.pdf 中的行.

As you see, both the numbers from document1.pdf and the lines from overlay.pdf are there.

当心! .此代码是概念验证,尚不能用于一般生产用途.例如完全忽略旋转页面条目...

这篇关于PDFBox叠加失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆