I came across many examples that use the appendFormAsLayer method of the PDFBox Layer Utility, as shown below:
public PDOptionalContentGroup appendFormAsLayer(PDPage targetPage, PDXObjectForm form, AffineTransform transform, String layerName) throws IOException { PDDocumentCatalog catalog = targetDoc.getDocumentCatalog(); PDOptionalContentProperties ocprops = catalog.getOCProperties(); if (ocprops == null) { ocprops = new PDOptionalContentProperties(); catalog.setOCProperties(ocprops); } if (ocprops.hasGroup(layerName)) { throw new IllegalArgumentException("Optional group (layer) already exists: " + layerName); } PDOptionalContentGroup layer = new PDOptionalContentGroup(layerName); ocprops.addGroup(layer); PDResources resources = targetPage.findResources(); PDPropertyList props = resources.getProperties(); if (props == null) { props = new PDPropertyList(); resources.setProperties(props); }
What is the meaning of βMCβ in the getPDFName call in the previous code?
I wrote the following code to insert a watermark on each page of an existing pdf and include each additional content group.
LayerUtility layerUtility = new LayerUtility(document); PDXObjectForm form = layerUtility.importPageAsForm(overlayDoc, 0); for (int i = 0; i < document.getDocumentCatalog().getAllPages().size(); i++) { PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(i); PDOptionalContentGroup ocGroup = layerUtility.appendFormAsLayer(page, form, new AffineTransform(), "watermark" + i); } PDOptionalContentProperties ocprops = document.getDocumentCatalog().getOCProperties(); for (String groupName : ocprops.getGroupNames()) { if (groupName.startsWith("watermark")) { ocprops.setGroupEnabled(groupName, true); } }
Setting the group to enable or disable "setGroupEnabled (groupName, true)" makes it appear for both display and printing. According to other information that I investigated on this subject, you can fine-tune it when additional content is displayed, which indicates the existence of the onScreen and onPrint Boolean attributes, which can be set to determine the visibility of the content. See https://acrobatusers.com/tutorials/watermarking-a-pdf-with-javascript
Is there a way to use the PDFBox to make the watermark appear when printing, but not when displaying? If not, any suggestions for alternative solutions will be appreciated.
Here is additional code to create a pdf watermark from the line (createOverlay) and the function (addWatermark) that calls LayerUtility, which passes the watermark document. All that is required is to create a PDDocument from any existing pdf file and transfer it using a watermark string.
public PDDocument addWatermark(PDDocument document, String text) throws IOException { PDDocument overlayDoc = createOverlay(text); // Create the watermark in an optional content group LayerUtility layerUtility = new LayerUtility(document); PDXObjectForm form = layerUtility.importPageAsForm(overlayDoc, 0); for (int i = 0; i < document.getDocumentCatalog().getAllPages().size(); i++) { PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(i); layerUtility.appendFormAsLayer(page, form, new AffineTransform(), "watermark" + i); } return document; } private PDDocument createOverlay(String text) throws IOException { // Create a document and add a page to it PDDocument document = new PDDocument(); PDPage page = new PDPage(); document.addPage(page); PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState(); // Set the transparency/opacity extendedGraphicsState.setNonStrokingAlphaConstant(0.4f); if (page.findResources() == null) { page.setResources(new PDResources()); } PDResources resources = page.findResources();// Get the page resources. // Get the defined graphic states. if (resources.getGraphicsStates() == null) { resources.setGraphicsStates(new HashMap<String, PDExtendedGraphicsState>()); } Map<String, PDExtendedGraphicsState> graphicsStateDictionary = resources.getGraphicsStates(); if (graphicsStateDictionary != null){ graphicsStateDictionary.put("TransparentState", extendedGraphicsState); resources.setGraphicsStates(graphicsStateDictionary); } // the x/y coords Float xVal = 0f; //Float.parseFloat(config.getProperty("ss.xVal")); Float yVal = 0f; //Float.parseFloat(config.getProperty("ss.yVal")); // Start a new content stream which will "hold" the to be created content PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true); contentStream.appendRawCommands("/TransparentState gs\n"); // Create the text and position it contentStream.beginText(); contentStream.setFont(font, fontSize); contentStream.setTextRotation(Math.PI/4,page.getMediaBox().getWidth()/4,page.getMediaBox().getHeight()/4); contentStream.setNonStrokingColor(210,210,210); //light grey contentStream.moveTextPositionByAmount(xVal, yVal); contentStream.drawString(text); contentStream.endText(); // Make sure that the content stream is closed: contentStream.close(); //return the string doc return document; }