使用PDFBox提取PDF裁剪区域文本失败,如何正确实现?
解决PDFBox提取裁剪区域内文本的问题
为什么设置CropBox后提取文本仍包含区域外内容?
PDF的CropBox仅定义页面显示/打印时的可见区域,并不会从文档中移除底层的文本内容。PDFTextStripper默认会提取页面上所有文本,完全不受CropBox限制,这就是你遇到问题的核心原因。
你使用PDFTextStripperByArea的错误点
你之前通过getCropBox().toGeneralPath().getBounds2D()转换区域的方式可能丢失了PDF坐标系统的关键信息,导致区域匹配失效。直接使用PDRectangle对象传入addRegion才是正确的做法。
正确解决方案
方案1:正确使用PDFTextStripperByArea
直接利用页面的CropBox创建提取区域,注意PDF的坐标系统原点在页面左下角,Y轴向上,如果你的原始坐标是基于左上角的,需要先做坐标转换。
示例代码:
// 初始化文本提取器 PDFTextStripperByArea areaStripper = new PDFTextStripperByArea(); PDPage page = document.getPage(0); PDRectangle cropBox = page.getCropBox(); // 直接用CropBox创建提取区域 areaStripper.addRegion("targetRegion", cropBox); // 提取指定页面的区域文本 areaStripper.extractRegions(page); String regionText = areaStripper.getTextForRegion("targetRegion");
如果你的startX/startY是基于页面左上角的坐标,需要先转换为PDF标准坐标(左下角原点):
// 假设pageHeight是页面的MediaBox高度 float pdfY = page.getMediaBox().getHeight() - startY - height; PDRectangle correctCropBox = new PDRectangle(startX, pdfY, width, height); areaStripper.addRegion("targetRegion", correctCropBox);
方案2:手动过滤文本位置(更精确控制)
如果需要对文本片段做更精细的过滤,可以继承PDFTextStripper,重写writeString方法,判断每个文本位置是否在CropBox范围内:
示例代码:
PDPage page = document.getPage(0); PDRectangle cropBox = page.getCropBox(); PDFTextStripper filteredStripper = new PDFTextStripper() { @Override protected void writeString(String text, List<TextPosition> textPositions) throws IOException { // 遍历每个文本片段的位置,判断是否与CropBox有交集 for (TextPosition tp : textPositions) { float textX = tp.getX(); float textY = tp.getY(); float textEndX = textX + tp.getWidth(); float textEndY = textY + tp.getHeight(); // 检查文本边界是否在CropBox内 boolean isInCropBox = (textEndX >= cropBox.getLowerLeftX()) && (textX <= cropBox.getUpperRightX()) && (textEndY >= cropBox.getLowerLeftY()) && (textY <= cropBox.getUpperRightY()); if (isInCropBox) { super.writeString(text, textPositions); break; // 只要有一个字符在区域内就写入整段文本,可按需调整逻辑 } } } }; // 提取过滤后的文本 String filteredText = filteredStripper.getText(document);
内容的提问来源于stack exchange,提问作者Arjun C E
相关产品推荐
相关产品推荐

