Java使用PDFBox实现PDPage中PDF注释扁平化的方法咨询
PDFBox实现PDPage页面注释扁平化方案
注释扁平化的核心逻辑是将注释自带的外观流直接写入页面内容流,移除原注释对象后,所有内容都会作为页面普通元素展示,无需查看器支持注释解析能力。
实现步骤
- 获取目标
PDPage对象的全部注释:调用page.getAnnotations()获取注释列表 - 遍历每一条注释,读取注释的正常外观流
PDAppearanceStream - 匹配注释在页面的坐标位置,将外观流写入到页面内容流的对应位置
- 所有注释写入完成后,清空页面注释列表完成扁平化操作
可运行代码示例
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotation; import org.apache.pdfbox.pdmodel.PDPageContentStream; import org.apache.pdfbox.util.Matrix; import java.io.File; import java.io.IOException; import java.util.List; public class AnnotationFlattener { public static void flattenSinglePage(PDDocument doc, PDPage page) throws IOException { List<PDAnnotation> annotationList = page.getAnnotations(); if (annotationList.isEmpty()) { return; } // 以追加模式打开页面内容流,保留原有页面内容 try (PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true)) { for (PDAnnotation anno : annotationList) { // 跳过无有效外观流的特殊注释(如弹出注释、未初始化的自定义注释) if (anno.getNormalAppearanceStream() == null) { continue; } // 基于注释的矩形区域计算坐标偏移 Matrix transMatrix = Matrix.getTranslateInstance( anno.getRectangle().getLowerLeftX(), anno.getRectangle().getLowerLeftY() ); // 将注释外观作为表单XObject写入页面内容 cs.drawForm(anno.getNormalAppearanceStream(), transMatrix); } } // 移除页面所有原注释对象 page.setAnnotations(null); } public static void main(String[] args) throws IOException { try (PDDocument document = PDDocument.load(new File("你的输入PDF路径.pdf"))) { // 遍历所有页面批量扁平化 for (PDPage page : document.getPages()) { flattenSinglePage(document, page); } document.save("输出扁平化后的PDF路径.pdf"); } } }
注意事项
- 存在旋转角度的页面需要额外对坐标做旋转变换,否则会出现注释位置偏移问题
- 数字签名、加密注释等特殊类型注释不建议做扁平化处理,上述代码会自动跳过无外观流的注释
- 请使用PDFBox 2.0.20及以上版本运行上述代码,低版本的
drawForm方法存在坐标计算bug
内容的提问来源于stack exchange,提问作者PereZix
相关产品推荐
相关产品推荐

