如何用iText7彻底移除PDF中的纯文本对象?
使用iText7彻底移除PDF中的所有文本(替代PDFCleanUp方案)
你可以通过直接解析并重写PDF的内容流,跳过所有文本相关的绘制操作,来彻底移除PDF中的文本对象,避免PDFCleanUp添加背景框的问题。以下是具体实现方案:
核心思路
遍历PDF的每一页及嵌套的Form XObject,监听内容流中的事件:
- 识别文本块的开始(
BEGIN_TEXT)和结束(END_TEXT)标记,跳过该区间内的所有文本渲染操作 - 保留并重新绘制非文本内容(如路径、图像、阴影等)
Java代码实现
主处理逻辑
import com.itextpdf.kernel.pdf.*; import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor; import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfCanvasListener; import com.itextpdf.kernel.pdf.canvas.parser.data.IEventData; import com.itextpdf.kernel.pdf.canvas.parser.EventType; import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo; import com.itextpdf.kernel.pdf.canvas.parser.data.PathRenderInfo; import com.itextpdf.kernel.pdf.canvas.parser.data.ImageRenderInfo; import java.io.IOException; public class RemovePdfText { public static void main(String[] args) throws IOException { try (PdfReader reader = new PdfReader("input.pdf"); PdfWriter writer = new PdfWriter("output.pdf"); PdfDocument pdfDoc = new PdfDocument(reader, writer)) { // 遍历所有页面 for (int pageNum = 1; pageNum <= pdfDoc.getNumberOfPages(); pageNum++) { PdfPage page = pdfDoc.getPage(pageNum); processPageContent(page, pdfDoc); processPageFormXObjects(page, pdfDoc); } } } // 处理页面直接内容流 private static void processPageContent(PdfPage page, PdfDocument pdfDoc) { PdfCanvasProcessor processor = new PdfCanvasProcessor(new TextRemovalListener(page.newContentStreamBefore(), page.getResources(), pdfDoc)); processor.processPageContent(page); page.removeContentStream(); } // 处理页面资源中的Form XObject private static void processPageFormXObjects(PdfPage page, PdfDocument pdfDoc) { PdfResources resources = page.getResources(); if (resources == null) return; PdfDictionary xObjects = resources.getPdfObject().getAsDictionary(PdfName.XObject); if (xObjects == null) return; for (PdfName xObjName : xObjects.keySet()) { PdfStream xObjStream = xObjects.getAsStream(xObjName); if (PdfName.Form.equals(xObjStream.getAsName(PdfName.Subtype))) { PdfFormXObject formXObject = new PdfFormXObject(xObjStream); processFormXObjectContent(formXObject, pdfDoc); } } } // 处理Form XObject内容流 private static void processFormXObjectContent(PdfFormXObject formXObj, PdfDocument pdfDoc) { PdfCanvasProcessor processor = new PdfCanvasProcessor(new TextRemovalListener(formXObj.getPdfObject(), formXObj.getResources(), pdfDoc)); processor.processContent(formXObj.getPdfObject().getBytes(), formXObj.getResources()); formXObj.getPdfObject().setData(processor.getCanvas().getContentStreamBytes()); } // 自定义监听器:移除文本,保留其他内容 private static class TextRemovalListener implements IPdfCanvasListener { private final PdfCanvas canvas; private boolean inTextBlock = false; public TextRemovalListener(PdfStream contentStream, PdfResources resources, PdfDocument pdfDoc) { this.canvas = new PdfCanvas(contentStream, resources, pdfDoc); } @Override public void eventOccurred(IEventData data, EventType type) { switch (type) { case BEGIN_TEXT: inTextBlock = true; break; case END_TEXT: inTextBlock = false; break; case TEXT_RENDER_INFO: // 跳过所有文本渲染操作 break; case PATH_RENDER_INFO: if (!inTextBlock) { PathRenderInfo pathInfo = (PathRenderInfo) data; canvas.addPath(pathInfo.getPath()); switch (pathInfo.getOperation()) { case STROKE: canvas.stroke(); break; case FILL: canvas.fill(); break; case FILL_STROKE: canvas.fillStroke(); break; } } break; case IMAGE_RENDER_INFO: if (!inTextBlock) { ImageRenderInfo imageInfo = (ImageRenderInfo) data; PdfImageXObject image = imageInfo.getImage(); canvas.addImage(image, imageInfo.getImageMatrix(), false); } break; // 可根据需求添加其他非文本类型的处理(如Shading等) default: if (!inTextBlock) { // 其他非文本操作可按需处理 } break; } } @Override public EventType[] getSupportedEvents() { return new EventType[]{ EventType.BEGIN_TEXT, EventType.END_TEXT, EventType.TEXT_RENDER_INFO, EventType.PATH_RENDER_INFO, EventType.IMAGE_RENDER_INFO }; } } }
关键说明
- 依赖引入:确保项目中包含iText7核心库,Maven依赖示例:
<dependency> <groupId>com.itextpdf</groupId> <artifactId>kernel</artifactId> <version>7.2.5</version> </dependency>
- 嵌套内容处理:代码同时处理了页面直接内容和Form XObject中的文本,覆盖大多数PDF的场景
- 内容保留:仅移除
PdfName.Text类型的文本绘制操作,保留所有路径、图像等非文本元素,不会修改原始背景
C#版本参考
逻辑与Java一致,语法调整为C#风格,例如使用PdfCanvasProcessor和IPdfCanvasListener接口,处理页面和Form XObject的方式类似。
内容的提问来源于stack exchange,提问作者argledhel
相关产品推荐
相关产品推荐

