使用Apache PDFBox Overlay添加PDF水印,Acrobat无法识别该水印怎么办
问题原因
你用Overlay类实现的是页面内容平铺叠加,只是把水印PDF的内容合并到原始PDF的页面内容中,并没有生成Acrobat能识别的结构化水印对象。Acrobat的水印属于PDF标准中的**可选内容组(OCG)**结构,这类结构支持单独编辑、隐藏或删除操作,而简单的内容叠加无法被识别为这类结构化元素。
解决方案:生成Acrobat可识别的水印
要让Acrobat能识别并编辑水印,需要通过PDFBox创建关联到OCG的水印内容,以下是具体实现代码:
import org.apache.pdfbox.pdmodel.*; import org.apache.pdfbox.pdmodel.common.PDRectangle; import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject; import org.apache.pdfbox.pdmodel.graphics.optionalcontent.PDOptionalContentGroup; import org.apache.pdfbox.pdmodel.graphics.optionalcontent.PDOptionalContentProperties; import org.apache.pdfbox.pdmodel.PDPageContentStream; import java.io.File; import java.io.IOException; public class AddAcrobatRecognizableWatermark { public static void main(String[] args) throws IOException { // 加载原始PDF文档 try (PDDocument originalDoc = PDDocument.load(new File("original.pdf"))) { // 加载水印PDF(假设为单页,内容为图像水印) try (PDDocument watermarkDoc = PDDocument.load(new File("watermark.pdf"))) { PDPage watermarkPage = watermarkDoc.getPage(0); PDImageXObject watermarkImage = null; // 从水印页面提取图像资源 for (COSName name : watermarkPage.getResources().getXObjectNames()) { if (watermarkPage.getResources().getXObject(name) instanceof PDImageXObject) { watermarkImage = (PDImageXObject) watermarkPage.getResources().getXObject(name); break; } } if (watermarkImage == null) { throw new IOException("水印PDF中未找到图像资源"); } // 创建可选内容组(OCG)——Acrobat识别水印的核心 PDOptionalContentProperties ocProps = originalDoc.getDocumentCatalog().getOCProperties(); if (ocProps == null) { ocProps = new PDOptionalContentProperties(); originalDoc.getDocumentCatalog().setOCProperties(ocProps); } PDOptionalContentGroup watermarkOCG = new PDOptionalContentGroup("Watermark"); ocProps.addGroup(watermarkOCG); // 遍历原始PDF的每一页添加水印 for (PDPage page : originalDoc.getPages()) { PDRectangle pageSize = page.getMediaBox(); float pageWidth = pageSize.getWidth(); float pageHeight = pageSize.getHeight(); float imgWidth = watermarkImage.getWidth(); float imgHeight = watermarkImage.getHeight(); // 计算水印居中位置 float xPos = (pageWidth - imgWidth) / 2; float yPos = (pageHeight - imgHeight) / 2; // 向页面追加内容流,关联OCG try (PDPageContentStream contentStream = new PDPageContentStream( originalDoc, page, PDPageContentStream.AppendMode.APPEND, true, true)) { // 标记内容属于水印OCG contentStream.beginMarkedContent(COSName.OC, watermarkOCG); // 绘制水印图像 contentStream.drawImage(watermarkImage, xPos, yPos, imgWidth, imgHeight); contentStream.endMarkedContent(); } } // 保存最终文档 originalDoc.save("watermarked_compatible.pdf"); } } } }
关键说明
- 可选内容组(OCG):这是让Acrobat识别水印的核心,生成的水印会被归类到Acrobat的可选内容列表中,你可以通过「工具>编辑PDF>水印」菜单直接编辑或删除,也能在「导航窗格>内容」中控制水印的显示/隐藏。
- 如果你的水印PDF包含的是文本或矢量图形而非图像,需要提取水印页面的内容流并复制到原始页面的OCG标记中,核心逻辑和上述代码一致,仅需替换图像绘制部分为内容流复制操作。
内容的提问来源于stack exchange,提问作者Tanmay Sharma
相关产品推荐
相关产品推荐

