使用 C# 定位 PDF 文本:提取文字在页面上的坐标位置

在 PDF 自动化处理中,获取指定文本的精确坐标是一项基础且高频的需求,常用于自动盖章、区域内容校验或动态表单填充。Free Spire.PDF for .NET 作为一款免费、无依赖的 PDF 组件,提供了相对简洁的 API 来实现这一功能。本文将从坐标系概念入手,结合完整代码示例,说明如何定位单个文本实例的坐标,并讨论多行文本与边界框的取舍。


理解 PDF 页面坐标系

在编写代码之前,需要先明确 Spire.PDF 使用的坐标系约定。PdfPageBase 表示一个 PDF 页面,页面上的坐标原点位于内容区域的左上角 ,X 轴水平向右延伸,Y 轴垂直向下延伸。这与屏幕坐标系一致,但与数学中"原点在左下角、Y 轴向上"的习惯相反。后续获取到的坐标值均基于这一约定,因此在将坐标用于绘图或注释时,无需额外翻转 Y 轴。


核心 API 一览

获取指定文本坐标主要依赖三个类型:

类型 作用
PdfTextFinder 在指定页面上执行文本查找
PdfTextFindOptions 控制查找行为(是否忽略大小写、是否全词匹配等)
PdfTextFragment 表示一个查找结果,承载文本内容与位置信息

PdfTextFragment 提供两个与坐标相关的成员:

  • Positions :PointF[] 类型,表示文本的起始点坐标(通常是左上角或基线起点,取决于 PDF 内部结构)。
  • Bounds :RectangleF[] 类型,表示文本的边界矩形数组。当查找的文本跨越换行时,会返回多个矩形。

对于大多数"获取某个词坐标"的场景,Positions[0] 足够使用;若需要高亮或绘制矩形框,Bounds[0] 更直接。


完整代码示例:获取指定文本的坐标

以下示例遍历 PDF 所有页面,查找字符串 "target audience"(忽略大小写),输出每个匹配项的 X、Y 坐标。

csharp 复制代码
using Spire.Pdf;
using Spire.Pdf.Texts;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace GetTextCoordinates

{

class Program

{

static void Main(string[] args)

{

// 加载 PDF 文档

PdfDocument doc = new PdfDocument();

doc.LoadFromFile(@"C:\path\to\input.pdf");


// 遍历每一页

foreach (PdfPageBase page in doc.Pages)

{

// 基于当前页创建查找器

PdfTextFinder finder = new PdfTextFinder(page);


// 配置查找选项:忽略大小写

PdfTextFindOptions options = new PdfTextFindOptions();

options.Parameter = TextFindParameter.IgnoreCase;

finder.Options = options;


// 执行查找,返回所有匹配的文本片段

List<PdfTextFragment> fragments = finder.Find("target audience");


foreach (PdfTextFragment fragment in fragments)

{

// Positions[0] 是文本的起始点坐标

PointF startPoint = fragment.Positions[0];

Console.WriteLine(

$"找到文本:"{fragment.Text}",坐标:({startPoint.X}, {startPoint.Y})"

);


// 如果需要边界矩形(用于高亮或框选)

RectangleF bounds = fragment.Bounds[0];

Console.WriteLine(

$"边界:X={bounds.X}, Y={bounds.Y}, 宽={bounds.Width}, 高={bounds.Height}"

);

}

}

`doc.Close();`
`
}`
`
}`
`
}`
`
`

代码要点 :

  • PdfTextFinder 是按页创建 的,不能跨页复用。
  • finder.Find() 返回 List<PdfTextFragment>,即使只期望一个结果,也应使用集合遍历,以处理重复出现的情况。
  • fragment.Text 可直接读取匹配到的原文,便于校验查找是否正确。

Positions 与 Bounds 的取舍

这两个属性服务于不同目的,选择时需根据下游操作决定:

需求 推荐属性 原因
获取文本"起点"用于插入内容或跳转 Positions[0] 轻量,直接给出一个点
绘制高亮矩形、判断文本是否在某个区域内 Bounds[0] 包含宽高,可完整覆盖文本区域
文本跨越换行 Bounds(遍历全部元素) 单行 Bounds[0] 不完整,需合并多个矩形

一个容易忽略的细节是:当查找的文本跨越两行或更多行时,Bounds 数组会包含多个 RectangleF,每个矩形对应一行中的片段。如果业务逻辑要求"整段文本的坐标",需要对这些矩形做并集运算:

csharp 复制代码
RectangleF union = fragments[0].Bounds[0];
for (int i = 1; i < fragments[0].Bounds.Length; i++)
{
    union = RectangleF.Union(union, fragments[0].Bounds[i]);
}

查找选项对结果的影响

PdfTextFindOptions.Parameter 控制匹配策略,直接影响能否找到目标文本以及返回的坐标是否准确:

  • TextFindParameter.IgnoreCase :忽略大小写,适用于用户输入不确定的场景。
  • TextFindParameter.WholeWord :仅匹配完整单词。若查找 ".NET",使用全词匹配可避免命中 "ASP.NET Core" 中的部分内容。
  • 两者可组合 :通过位运算或依次赋值实现更精确的匹配。

若查找结果为空,首先应检查是否因大小写或全词限制过严导致漏匹配。


常见问题与注意事项

1. PDF 必须是"可搜索"的

PdfTextFinder 依赖于 PDF 中嵌入的文本层。纯扫描图片生成的 PDF(无 OCR 文本层)无法通过此方式获取坐标,此时需要先进行 OCR 处理。

2. Positions[0] 的含义并非固定"左上角"

部分 PDF 中,Positions[0] 可能对应文本的基线起点而非左上角,具体取决于 PDF 内部的文本矩阵。如果坐标用于视觉对齐,建议以 Bounds 为准。

3. 坐标单位

Spire.PDF 返回的坐标单位是点(point) ,1 point = 1/72 英寸。若后续需要换算为像素或毫米,按此比例转换即可。

4. 遍历页面时及时释放资源

处理大文档时,建议在每页处理完毕后释放 PdfTextFinder 相关对象,或至少确保 PdfDocument 在 finally 块中关闭,避免文件句柄被占用。


小结

使用 Free Spire.PDF for .NET 获取 PDF 文本坐标的路径清晰:加载文档 → 按页创建 PdfTextFinder → 配置查找选项 → 调用 Find() → 从 PdfTextFragment 中读取 Positions 或 Bounds。核心决策在于根据下游用途选择 Positions[0](单点)还是 Bounds(矩形区域),并对多行文本的边界合并做额外处理。坐标系以左上角为原点、Y 轴向下,这一点在将坐标回写到 PDF 或界面时保持一致性即可。