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: