You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 09:36:21