如何使用Apache PDFBox检测PDF水印及水印边距是否符合6.35mm要求
用Apache PDFBox检测PDF水印并验证边距合规性
核心思路拆解
PDF水印常见存在形式:页面内容层的文本/图形/图像、页面注释(Annotation)、嵌入的XObject。要完成需求,需分两步:遍历PDF页面提取所有可能的水印元素,再验证这些元素的边界是否符合边距要求。
第一步:检测水印元素
1. 解析页面内容层元素
使用PDFBox的PDFStreamEngine自定义处理器,拦截文本、图形、图像的绘制指令,记录它们的边界框(Bounding Box)。这类元素通常是直接绘制在页面上的批量水印。
示例代码片段:
public class WatermarkDetector extends PDFStreamEngine { private List<Rectangle2D> elementBounds = new ArrayList<>(); public WatermarkDetector() throws IOException { super(); // 拦截文本绘制指令,记录文本边界 addOperator(new ShowText() { @Override public void processOperator(Operator operator, List<COSBase> arguments) throws IOException { PDTextPosition textPos = getTextPosition(); if (textPos != null) { elementBounds.add(textPos.getBoundingBox()); } super.processOperator(operator, arguments); } }); // 可扩展添加路径填充、图像绘制的Operator处理器,捕获图形/图像水印 } public List<Rectangle2D> getElementBounds() { return elementBounds; } }
遍历页面使用:
try (PDDocument document = PDDocument.load(new File("target.pdf"))) { for (PDPage page : document.getPages()) { WatermarkDetector detector = new WatermarkDetector(); detector.processPage(page); List<Rectangle2D> elements = detector.getElementBounds(); // 可通过元素的重复特征、特定文本内容筛选出水印元素 } }
2. 检查页面注释
部分水印会以注释形式添加(如PDAnnotationStamp),直接遍历页面注释集合即可:
for (PDAnnotation annot : page.getAnnotations()) { if (annot instanceof PDAnnotationStamp) { PDAnnotationStamp stamp = (PDAnnotationStamp) annot; elementBounds.add(stamp.getRectangle().getRectangle2D()); } }
第二步:验证边距合规性
PDF默认用户单位为1/72英寸,¼英寸换算为18用户单位(72 * 0.25 = 18)。先获取页面实际尺寸(优先用TrimBox,无则用MediaBox),再计算安全区域:
PDPage page = ...; PDRectangle pageBox = page.getTrimBox() != null ? page.getTrimBox() : page.getMediaBox(); float pageWidth = pageBox.getWidth(); float pageHeight = pageBox.getHeight(); // 安全区域边界(各边留出18用户单位) float safeLeft = 18; float safeRight = pageWidth - 18; float safeBottom = 18; float safeTop = pageHeight - 18;
遍历水印元素,检查其边界是否完全落在安全区域内:
boolean isMarginCompliant = true; for (Rectangle2D bounds : watermarkBounds) { if (bounds.getMinX() < safeLeft || bounds.getMaxX() > safeRight || bounds.getMinY() < safeBottom || bounds.getMaxY() > safeTop) { isMarginCompliant = false; break; } }
注意事项
- 半透明水印仍需检测实际绘制区域,不能忽略透明度属性
- 由多个小元素组成的复杂水印,需合并所有相关元素的边界后再验证
- 存在旋转的页面,需先修正坐标系再计算边界
内容的提问来源于stack exchange,提问作者Messy Rider
相关产品推荐
相关产品推荐

