PDFBox Overlay fails

纵然是瞬间 提交于 2019-12-14 03:48:57

问题


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()

}

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

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.


回答1:


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

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:

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.

A work-around using blend mode 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.

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)

Applying them to your sample documents

@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"));
    }
}

results in

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

Beware! This code is a proof-of-concept and not ready for general productive use. It e.g. completely ignores Rotate page entries...



来源:https://stackoverflow.com/questions/29095822/pdfbox-overlay-fails

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!