使用 pdfbox (1.7) 在包含图像的 pdf 上添加水印

Add a watermark on a pdf that contains images using pdfbox (1.7)

我使用了建议的代码:

为现有 pdf 添加水印。 不幸的是,生成的 pdf 已损坏。当我打开文档时,pdf reader 抱怨:"An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem"

文档已打开,但未显示图像。

似乎所有的 pdf 都会发生这种情况。值得一提的是,它也发生在仅使用 Overlay class.

的不同实现中

以下url指向我用于测试的pdf:

A pdf with an image

测试此转换的代码是:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.common.PDStream;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.PDExtendedGraphicsState;
import org.apache.pdfbox.pdmodel.graphics.xobject.PDXObjectForm;
import org.apache.pdfbox.util.MapUtil;

/**
 * This test is about overlaying with special effect.
 * 
 * @author mkl
 */
public class OverlayWithEffect
{
    final static File RESULT_FOLDER = new File("target/test-outputs", "assembly");

    public static 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)
        {
            if (page.getResources() == null) {
                page.setResources(page.findResources());
            }

            if (page.getResources() != null) {
                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();
            }
        }
    }

    public static 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;
    }


    public static void main(String[] args) throws COSVisitorException, IOException
    {
        InputStream sourceStream = new FileInputStream("x:/pdf-test.pdf");
        InputStream overlayStream = new FileInputStream("x:/draft.pdf");
        try {
            final PDDocument document = PDDocument.load(sourceStream);
            final PDDocument overlay = PDDocument.load(overlayStream);

            overlayWithDarkenBlendMode(document, overlay);

            document.save("x:/da-draft-5.pdf");
            document.close();
        }
        finally {
            sourceStream.close();
            overlayStream.close();
        }
    }    
}

我正在使用 1.7 版的 pdfbox。

谢谢

根据mkl的建议,可能是我使用的pdfbox版本有问题。