javaoverlaypdfboxwatermark

How can I add watermark with apache pdfbox


I am adding watermark on an existing pdf. As far as I know there are 2ways to achieve the goal.

But I either way just cover all the original contents.

Follow is what I wrote till now

The Service

public class TestPdf {

    // Method #1. This method will add overlay pdf to the original one
    public PDDocument addWatermark(PDDocument originalDocument, PDDocument overlayDocument) throws IOException {
        Overlay overlay = new Overlay();
        overlay.setOverlayPosition(Overlay.Position.BACKGROUND);
        overlay.setInputPDF(originalDocument);
        overlay.setAllPagesOverlayPDF(overlayDocument);
        PDDocument markedDocument = overlay.overlay(Collections.emptyMap());
        overlay.close();
        return markedDocument;
    }

    // Method #2. This method will add transparent image to the original pdf
    public PDDocument addImage(PDDocument originalDocument, String watermarkPath, float x, float y, float alpha) throws IOException {
        PDImageXObject watermarkImage = PDImageXObject.createFromFile(watermarkPath, originalDocument);
        PDExtendedGraphicsState pdExtendedGraphicsState = new PDExtendedGraphicsState();
        pdExtendedGraphicsState.setNonStrokingAlphaConstant(alpha);

        for (int i = 0; i < originalDocument.getNumberOfPages(); i++) {
            PDPage page = originalDocument.getPage(i);
            PDPageContentStream contentStream = new PDPageContentStream(originalDocument, page);
            contentStream.setGraphicsStateParameters(pdExtendedGraphicsState);
            contentStream.drawImage(watermarkImage, x, y);
            contentStream.close();
        }
        return originalDocument;
    }
}

And Test method like

public class TestRunner {
    private void writeFile(String outPath, PDDocument document) throws IOException {
        File outFile = new File(outPath);
        FileOutputStream fileOutputStream = new FileOutputStream(outFile);
        document.saveIncremental(fileOutputStream);
    }
    
    @Test
    public void addWatermark() throws Exception {
        TestPdf sut = new TestPdf();
        File inFile = new File(UNSIGNED_PDF_FILE);
        PDDocument document = Loader.loadPDF(inFile);
        File overlayFile = new File(WATERMARK_PDF_FILE);
        PDDocument overlay = Loader.loadPDF(overlayFile);
        PDDocument markedDocument = sut.addWatermark(document, overlay);
        writeFile(WATERMARKED_FILE, markedDocument);
    }
    
    @Test
    public void addTransparentImage() throws ExportException {
        TestPdf sut = new TestPdf();        
        File inFile = new File(UNSIGNED_PDF_FILE);
        PDDocument document = Loader.loadPDF(inFile);
        PDDocument watermarkAddedDocument = sut.addImage(document, WATERMARK_PNG_FILE, 200, 200, 0.1F);
        writeFile(IMAGED_APPENDED_FILE, watermarkAddedDocument);
    }
}

This code makes 2 pdf files. one with overlay pdf and the other one with transparent image.

The problem is the original contents does not show up

Is there anything wrong with setting image or overlay?

==== Updated ====

Setting overlay.setOverlayPosition(Overlay.Position.FOREGROUND) makes work.

However still got no clue about adding image.


Solution

  • You want to add content to the page. But the way you construct a PDPageContentStream

    new PDPageContentStream(originalDocument, page);
    

    replaces the current page content by your new content. Thus, you have to use a different constructor here with parameters that allow you to append new content. As you found out in response to a comment to that effect, using

    new PDPageContentStream(originalDocument, page, PDPageContentStream.AppendMode.APPEND, true, true)
    

    makes your code work as intended.