使用iText7 C#提取PDF指定区域文本异常问题求助
使用iText7 C#提取PDF指定区域文本异常的排查与解决方法
我希望使用iText7 C#提取PDF指定位置的文本,为此编写了如下代码:
PdfReader pdfRead = new PdfReader(file); PdfDocument pdfdoc = new PdfDocument(pdfRead); Rectangle rect = new Rectangle((float)4.090625, (float)58.384375, (float)76.60625, (float)40.1625); TextRegionEventFilter regionFilter = new TextRegionEventFilter(rect); StringBuilder builder = new StringBuilder(); for (int page = 1; page <= pdfdoc.GetNumberOfPages(); page++) { ITextExtractionStrategy strat = new FilteredTextEventListener(new LocationTextExtractionStrategy(), regionFilter); string str = PdfTextExtractor.GetTextFromPage(pdfdoc.GetPage(page), strat); Debug.WriteLine(str); }
该代码虽能提取矩形区域的文本,但无法获取我想要的目标区域内容,即便输入正确坐标也会随机提取文本。我尝试过其他库,可正常提取对应坐标的文本,但iText7无法实现。恳请帮忙排查代码是否存在问题,并提供解决方法。
问题排查与解决方法
1. 修正坐标体系匹配问题
iText7的PDF坐标原点为页面左下角,而多数工具或其他库默认以左上角为原点,这是最常见的坐标偏差原因:
- 坐标转换公式:
iTextY = 页面高度 - 工具获取的Y坐标 - 区域高度 - 获取页面高度的代码:
PdfPage currentPage = pdfdoc.GetPage(page); float pageHeight = currentPage.GetPageSize().GetHeight();
2. 替换默认过滤器的匹配逻辑
默认TextRegionEventFilter仅判断文本基线是否落在区域内,若文本基线不在区域,即便文字部分覆盖区域也会被过滤。可自定义过滤器,判断文本的整个包围盒是否与目标区域有交集:
public class TextBoundingBoxFilter : IEventListener { private readonly Rectangle _targetRect; private readonly IEventListener _delegateListener; public TextBoundingBoxFilter(Rectangle targetRect, IEventListener delegateListener) { _targetRect = targetRect; _delegateListener = delegateListener; } public void EventOccurred(IEventData data, EventType type) { if (type.Equals(EventType.RENDER_TEXT)) { TextRenderInfo renderInfo = (TextRenderInfo)data; Rectangle textRect = renderInfo.GetAscentLine().GetBoundingRectangle(); textRect.Merge(renderInfo.GetDescentLine().GetBoundingRectangle()); if (_targetRect.Intersects(textRect)) { _delegateListener.EventOccurred(data, type); } } else { _delegateListener.EventOccurred(data, type); } } public ICollection<EventType> GetSupportedEvents() { return _delegateListener.GetSupportedEvents(); } }
替换原代码中的过滤器使用逻辑:
for (int page = 1; page <= pdfdoc.GetNumberOfPages(); page++) { PdfPage currentPage = pdfdoc.GetPage(page); float pageHeight = currentPage.GetPageSize().GetHeight(); // 转换左上角坐标为iText7的左下角坐标 Rectangle rect = new Rectangle(4.090625f, pageHeight - 58.384375f - 40.1625f, 76.60625f, 40.1625f); ITextExtractionStrategy baseStrat = new LocationTextExtractionStrategy(); IEventListener filteredListener = new TextBoundingBoxFilter(rect, baseStrat); string str = PdfTextExtractor.GetTextFromPage(currentPage, filteredListener); Debug.WriteLine(str); }
3. 排查PDF文本的特殊布局情况
部分PDF存在文本块拆分、页面旋转等特殊情况:
- 处理页面旋转:
int rotation = currentPage.GetRotation(); Rectangle pageSize = currentPage.GetPageSizeWithRotation(); // 根据旋转角度调整坐标计算逻辑
- 调试文本真实坐标:
自定义策略输出所有文本的坐标,确认目标文本的实际位置:
public class DebugTextStrategy : LocationTextExtractionStrategy { public override void EventOccurred(IEventData data, EventType type) { if (type.Equals(EventType.RENDER_TEXT)) { TextRenderInfo info = (TextRenderInfo)data; Rectangle rect = info.GetAscentLine().GetBoundingRectangle(); Debug.WriteLine($"文本: {info.GetText()}, 坐标: X={rect.GetX()}, Y={rect.GetY()}, 宽={rect.GetWidth()}"); } base.EventOccurred(data, type); } }
使用该策略提取整页文本,根据输出调整目标区域坐标。
内容的提问来源于stack exchange,提问作者anass laraki
相关产品推荐
相关产品推荐

