Watermarking with PDFBox

Tags: , , , ,



I am trying to add a watermark to a PDF specifically with PDFBox. I’ve been able to get the image to appear on each page, but it loses the background transparency because it appears as though PDJpeg converts it to a JPG. Perhaps there’s a way to do it using PDXObjectImage.

Here is what I have written thus far:

public static void watermarkPDF(PDDocument pdf) throws IOException
{
    // Load watermark
    BufferedImage buffered = ImageIO.read(new File("C:\PDF_Test\watermark.png"));
    PDJpeg watermark = new PDJpeg(pdf, buffered);

    // Loop through pages in PDF
    List pages = pdf.getDocumentCatalog().getAllPages();
    Iterator iter = pages.iterator();
    while(iter.hasNext())
    {
        PDPage page = (PDPage)iter.next();

        // Add watermark to individual page
        PDPageContentStream stream = new PDPageContentStream(pdf, page, true, false);
        stream.drawImage(watermark, 100, 0);
        stream.close();
    }

    try 
    {
        pdf.save("C:\PDF_Test\watermarktest.pdf");
    } 
    catch (COSVisitorException e) 
    {
        e.printStackTrace();
    }
}

Answer

UPDATED ANSWER (Better version with easy way to watermark, thanks to the commentators below and @okok who provided input with his answer)

If you are using PDFBox 1.8.10 or above, you can add watermark to your PDF document easily with better control over what pages needs to be watermarked. Assuming you have a one page PDF document that has the watermark image, you can overlay this on the document you want to watermark as follows.

Sample Code using 1.8.10

import java.util.HashMap;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.Overlay;

public class TestPDF {
    public static void main(String[] args) throws Exception{
            PDDocument realDoc = PDDocument.load("originaldocument.pdf"); 
            //the above is the document you want to watermark                   

            //for all the pages, you can add overlay guide, indicating watermark the original pages with the watermark document.
            HashMap<Integer, String> overlayGuide = new HashMap<Integer, String>();
            for(int i=0; i<realDoc.getPageCount(); i++){
                overlayGuide.put(i+1, "watermark.pdf");
                //watermark.pdf is the document which is a one page PDF with your watermark image in it. Notice here that you can skip pages from being watermarked.
            }
            Overlay overlay = new Overlay();
            overlay.setInputPDF(realDoc);
            overlay.setOutputFile("final.pdf");
            overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
            overlay.overlay(overlayGuide,false);
           //final.pdf will have the original PDF with watermarks.

Sample using PDFBox 2.0.0 Release candidate

import java.io.File;
import java.util.HashMap;
import org.apache.pdfbox.multipdf.Overlay;
import org.apache.pdfbox.pdmodel.PDDocument;

public class TestPDF {

    public static void main(String[] args) throws Exception{        
        PDDocument realDoc = PDDocument.load(new File("originaldocument.pdf"));
        //the above is the document you want to watermark
        //for all the pages, you can add overlay guide, indicating watermark the original pages with the watermark document.

        HashMap<Integer, String> overlayGuide = new HashMap<Integer, String>();
        for(int i=0; i<realDoc.getNumberOfPages(); i++){
            overlayGuide.put(i+1, "watermark.pdf");
            //watermark.pdf is the document which is a one page PDF with your watermark image in it. 
            //Notice here, you can skip pages from being watermarked.
        }
        Overlay overlay = new Overlay();
        overlay.setInputPDF(realDoc);
        overlay.setOutputFile("final.pdf");
        overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
        overlay.overlay(overlayGuide);      
    }
}

If you want to use the new package org.apache.pdfbox.tools.OverlayPDF for overlays you can do this way. (Thanks the poster below)

String[] overlayArgs = {"C:/Examples/foreground.pdf", "C:/Examples/background.pdf", "C:/Examples/resulting.pdf"};
OverlayPDF.main(overlayArgs);
System.out.println("Overlay finished.");

OLD ANSWER Inefficient way, not recommended.

Well, OP asked how to do it in PDFBox, the first answer looks like an example using iText. Creating a watermark in PDFBox is really simple. The trick is, you should have an empty PDF document with the watermark image. Then all you have to do is Overlay this watermark document on the document that you want to add the watermark to.

PDDocument watermarkDoc = PDDocument.load("watermark.pdf");
//Assuming your empty document with watermark image in it.

PDDocument realDoc = PDDocument.load("document-to-be-watermarked.pdf");
//Let's say this is your document that you want to watermark. For example sake, I am opening a new one, you would already have a reference to PDDocument if you are creating one

Overlay overlay = new Overlay();
overlay.overlay(realDoc,watermarkDoc);
watermarkDoc.save("document-now-watermarked.pdf");

Caution: You should make sure you match the number of pages in both document..Otherwise, you would end up with a document with number of pages matching the one which has least number of pages. You can manipulate the watermark document and duplicate the pages to match your document.

Hope this helps.!



Source: stackoverflow