Adding Watermark to PDF using Java


Adding a text-based watermark to existing PDF using Java is quite simple using the Apache PDFBox opensource free library. This library is very handing and can be used to create new PDF and modify existing files.

This can be easily added to maven and Gradle based projects by adding the following reference.

Gradle dependency:

// https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox
compile group: 'org.apache.pdfbox', name: 'pdfbox', version: '2.0.21'

Maven dependency:

<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.21</version>
</dependency>

Example to add watermark on the existing pdf file:

public class AddTextWaterMark {

	public static void main(final String[] args) throws IOException {
		if (args.length != 3) {
			System.out.println("Provide input and output files");
		} else {
			final File srcFile = new File(args[0]);
			final File dstFile = new File(args[1]);
			final String text = args[2];
			// Loader class not found in original sample
			try (PDDocument doc = PDDocument.load(srcFile)) {
				// Loop through each page to add text water mark on each page
				for (final PDPage page : doc.getPages()) {
					final PDFont font = PDType1Font.HELVETICA;

					addWatermarkText(doc, page, font, text);
				}
				doc.save(dstFile);
			}
		}
	}

	private static void addWatermarkText(final PDDocument doc, final PDPage page, final PDFont font, final String text)
			throws IOException {
		try (PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true,
				true)) {
			final float fontHeight = 100; // arbitrary for short text
			final float width = page.getMediaBox().getWidth();
			final float height = page.getMediaBox().getHeight();
			final float stringWidth = font.getStringWidth(text) / 1000 * fontHeight;
			final float diagonalLength = (float) Math.sqrt(width * width + height * height);
			final float angle = (float) Math.atan2(height, width);
			final float x = (diagonalLength - stringWidth) / 2; // "horizontal" position in rotated world
			final float y = -fontHeight / 4; // 4 is a trial-and-error thing, this lowers the text a bit
			cs.transform(Matrix.getRotateInstance(angle, 0, 0));
			cs.setFont(font, fontHeight);
			// cs.setRenderingMode(RenderingMode.STROKE) // for "hollow" effect

			final PDExtendedGraphicsState gs = new PDExtendedGraphicsState();
			gs.setNonStrokingAlphaConstant(0.2f);
			gs.setStrokingAlphaConstant(0.2f);
			gs.setBlendMode(BlendMode.MULTIPLY);
			gs.setLineWidth(3f);
			cs.setGraphicsStateParameters(gs);

			// Set color
			cs.setNonStrokingColor(Color.red);
			cs.setStrokingColor(Color.red);

			cs.beginText();
			cs.newLineAtOffset(x, y);
			cs.showText(text);
			cs.endText();
		}
	}
}

In the above example, you can see, PDDocument.load method used to load the entire existing document and addWatermarkText function have been used to add watermark on each page.

PDPageContentStream class is the key class to add watermark, you can see in the above example for setting text font and font color of the watermark text.

Here is the sample output:

adding text water mark


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.