系列文章:
Python PDF神器PyMuPDF使用指南 (一)——安装和基础功能
Python PDF神器PyMuPDF使用指南 (二)——文件和文本功能
Python PDF神器PyMuPDF使用指南 (三)——图像和注释功能
Python PDF神器PyMuPDF使用指南 (四)——绘图、多线程和OCR功能
Python PDF神器PyMuPDF使用指南 (五)——命令行使用
Python PDF神器PyMuPDF使用指南 (六)——Document类详解
Python PDF神器PyMuPDF使用指南 (七)——Page类详解
Python PDF神器PyMuPDF使用指南 (八)——基础使用指南
正文:
PyMuPDF是一个高性能的Python库,用于PDF(和其他)文档的数据提取、分析、转换和操作。
Github地址为:pymupdf代码库
官方文档地址为:PyMuPDF文档
前面几篇文章详细介绍了PyMuPDF的主要功能以及命令行的使用,从前文开始介绍PyMuPDF做为Python库调用的主要类和方法。不过篇幅原因,只介绍了Document类的详细情况,本文会继续介绍Page类的详细情况。
Page类需要了解的前置类——Coordinates(坐标)类
简介
这是PyMuPDF文档中最常用的术语之一。坐标通常指一对数值 (x,y)(x, y),用于表示某个位置,比如矩形(Rect)的角、点(Point)等。这两个数值通常是浮点数,但在某些对象(如图像)中,它们只能是整数。
要确定一个坐标的位置,我们还需要知道 xx 和 yy 的参考点——换句话说,我们必须知道位置 (0,0)(0,0)(即“原点”)在哪里。一旦确定了 (0,0)(0,0)(即“原点”),我们就形成了一个“坐标系统”。
在文档处理过程中,存在多个不同的坐标系统。例如,PDF 页面和从 PDF 生成的图像的坐标系统就不同。因此,我们需要一种方法来将坐标从一个系统转换到另一个系统(有时还需要转换回来)。这个任务由 矩阵(Matrix) 来完成。矩阵是一种数学函数,它的作用类似于一个“因子”,可以与点或矩形进行“相乘”,从而得出另一个坐标系统中的对应点或矩形。变换矩阵的逆矩阵可以用于还原变换。类似于某个数乘以 3 后,可以通过除以 3(或乘以 1/31/3)来恢复原值。
坐标与图像(Coordinates and Images)
图像的坐标系统采用 整数坐标,其 原点(0,0) 位于图像的 左上角。
- xx 值的范围是 [0,width)[0, \text{width})
- yy 值的范围是 [0,height)[0, \text{height})
- yy 值 向下增加,即坐标的下方部分 yy 值更大。
在每张图像中,坐标是有限的,总共只有 width × height 个可能的位置。图像中的一个位置通常被称为 像素(pixel)。
图像的实际大小(例如以厘米或英寸为单位)取决于 分辨率(resolution),分辨率的单位是 DPI(每英寸点数,dots per inch,或 pixels per inch)。
要计算图像的打印尺寸,可以用 图像的宽度和高度分别除以对应的 DPI,从而得到尺寸(以英寸为单位)。
原点、点大小与 Y 轴方向(Origin Point, Point Size, and Y-Axis)
在 PDF 中,页面的原点 (0,0) 处于 左下角。
在 MuPDF 中,页面的原点 (0,0) 处于 左上角。
在 PDF 中,坐标是 浮点数,单位是 点(point):
- 1 点 = 1/72 英寸。
常见的文档页面尺寸:
- Letter 纸张大小为 8.5 × 11 英寸,对应 612 × 792 点。
- 在 PDF 坐标系统 中,Letter 纸张左上角 的坐标为 (0,792)(因为 Y 轴向上)。
- 在 MuPDF 坐标系统 中,Letter 纸张右下角 的坐标为 (612, 792)(而在 PDF 坐标系统中,它是 (612,0))。
理论上,PDF 页面上存在无限多个坐标位置,但通常 精确到小数点后 5 位 就足够了。
MuPDF 坐标系统与 PDF 坐标系统的转换(Coordinate System Conversion)
MuPDF 支持多种文档格式,PDF 只是其中之一。此外,MuPDF 也支持 图像作为文档(通常每个图像对应一页)。这就是 MuPDF 坐标系统采用左上角为原点 的一个原因——其 Y 轴方向与图像相同,向下递增。无论 PDF 还是 MuPDF,坐标值都是 浮点数。
在 MuPDF(以及 PyMuPDF)中,矩形 Rect(0, 0, 100, 100) 表示一个边长 100 点(= 1.39 英寸 或 3.53 厘米)的正方形,其 左上角 作为原点。要在 PDF 坐标系统 和 MuPDF 坐标系统 之间转换坐标,每个 Page
对象都有一个 Page.transformation_matrix
。使用其 逆矩阵,可以计算矩形的 PDF 坐标。例如:
page = doc.new_page(width=612, height=792) # 创建一个 Letter 页面
ptm = page.transformation_matrix # 获取页面的转换矩阵
# 使用逆矩阵将 MuPDF 坐标转换为 PDF 坐标
pymupdf.Rect(0, 0, 100, 100) * ~ptm
# 结果:Rect(0.0, 692.0, 100.0, 792.0)
备注(Footnotes)
[1] MuPDF 支持 PDF 文档之间的深度复制(deep-copying)
在跨 PDF 复制对象时,为了避免目标 PDF 中的数据重复,MuPDF 采用了 “graftmaps” 技术。这类似于一个临时映射表,每当需要复制对象时,会先检查其 xref 编号是否已存在于 graftmap:
- 如果已存在,则 跳过复制。
- 如果不存在,则 记录新 xref 并执行复制。
PyMuPDF 在两个地方使用了该技术:
Document.insert_pdf()
Page.show_pdf_page()
这种方式高效且节省资源,可避免复制多个相同的 图像、字体等 数据。然而,在以下情况下,仍然建议使用 垃圾回收(garbage collection,选项 4):
- 目标 PDF 不是全新/空白文件:Grafting 不会 检查目标 PDF 是否已经存在相同资源(如图像、字体)。
- 在多个来源 PDF 之间使用
Page.show_pdf_page()
:Grafting 仅适用于单个来源 PDF,无法跨多个 PDF 进行去重。例如,如果不同来源的 PDF 页面包含相同的图像,MuPDF 无法检测到重复,直到执行垃圾回收。
Page类概述
Page类说明
Page对象由 Document.load_page()
创建,或者可以通过索引 doc[n]
访问——它没有独立的构造函数。
Document和Page之间存在父子关系。如果Document被关闭或删除,则所有现存的Page对象(以及它们的子对象)都将变得不可用:如果继续使用Page的属性或方法,就会引发异常。
一些Page方法有对应的Document级别方法,以提高使用的便利性。本文末尾会做出相关总结。
注意
在本章的许多地方,我们都会用到“Coordinates(坐标)”这个术语。理解坐标的概念非常重要,建议熟悉前置的“坐标”部分内容。
修改页面
只有 PDF 文档支持修改页面属性以及添加或更改页面内容。PyMuPDF 允许你执行以下操作:
- 修改页面的旋转角度和可见部分(“裁剪框”)。
- 插入图像、其他 PDF 页面、文本和简单的几何对象。
- 添加批注(Annotations)和表单字段(Form Fields)。
注意
PyMuPDF 处理坐标时,所有坐标值必须 相对于未旋转的页面(自 v1.17.0 版本起)。这意味着:
1)设置旋转角度(Page.set_rotation()
)后,某些方法返回的坐标不会改变,例如Page.get_image_bbox()
、Page.get_text()
、批注的边界框等。
2)但Page.rect
和Page.bound()
会受旋转影响,它们始终反映当前页面的旋转情况。
3)如果你想计算旋转后的坐标,可以用Page.rotation_matrix
进行转换,或者使用Page.derotation_matrix
计算未旋转的坐标。
注意
在页面上 添加或更新批注、链接、表单字段后,如果你想立即操作它们(而不是等到页面被重新加载),建议调用Document.reload_page()
以确保所有更改都生效。
重新加载页面是推荐做法,虽然在某些情况下不是强制要求,但这样可以避免一些特殊的批注或小部件功能无法立即生效的问题,并确保:
- 正确生成 Pixmaps(像素图)
- 能够成功遍历页面上的所有批注、链接和表单字段
Page类的核心方法概况
下表列出了 Page
类的方法和属性。
批注(Annotations)相关
方法 / 属性 | 描述 |
---|---|
Page.add_caret_annot() | PDF 专属:添加“插入标记”批注 |
Page.add_circle_annot() | PDF 专属:添加圆形批注 |
Page.add_file_annot() | PDF 专属:添加文件附件批注 |
Page.add_freetext_annot() | PDF 专属:添加自由文本批注 |
Page.add_highlight_annot() | PDF 专属:添加高亮批注 |
Page.add_ink_annot() | PDF 专属:添加手写批注 |
Page.add_line_annot() | PDF 专属:添加直线批注 |
Page.add_polygon_annot() | PDF 专属:添加多边形批注 |
Page.add_polyline_annot() | PDF 专属:添加折线批注 |
Page.add_rect_annot() | PDF 专属:添加矩形批注 |
Page.add_redact_annot() | PDF 专属:添加“遮盖”批注 |
Page.add_squiggly_annot() | PDF 专属:添加波浪线批注 |
Page.add_stamp_annot() | PDF 专属:添加印章批注 |
Page.add_strikeout_annot() | PDF 专属:添加删除线批注 |
Page.add_text_annot() | PDF 专属:添加文本批注 |
Page.add_underline_annot() | PDF 专属:添加下划线批注 |
表单字段(Widgets)相关
方法 / 属性 | 描述 |
---|---|
Page.add_widget() | PDF 专属:添加 PDF 表单字段 |
Page.annot_names() | PDF 专属:获取批注和表单字段的名称列表 |
Page.annot_xrefs() | PDF 专属:获取批注和表单字段的 xref 列表 |
Page.annots() | 遍历页面上的所有批注 |
Page.apply_redactions() | PDF 专属:应用遮盖批注 |
Page.delete_annot() | PDF 专属:删除批注 |
Page.delete_widget() | PDF 专属:删除表单字段 |
绘制(Drawing)相关
方法 / 属性 | 描述 |
---|---|
Page.draw_bezier() | PDF 专属:绘制三次贝塞尔曲线 |
Page.draw_circle() | PDF 专属:绘制圆形 |
Page.draw_curve() | PDF 专属:绘制特殊贝塞尔曲线 |
Page.draw_line() | PDF 专属:绘制直线 |
Page.draw_polyline() | PDF 专属:绘制折线 |
Page.draw_rect() | PDF 专属:绘制矩形 |
Page.draw_zigzag() | PDF 专属:绘制锯齿状线条 |
文本、图像、链接相关
方法 / 属性 | 描述 |
---|---|
Page.get_text() | 提取页面文本 |
Page.get_textbox() | 提取矩形区域内的文本 |
Page.get_image_bbox() | PDF 专属:获取嵌入图片的边界框 |
Page.get_images() | PDF 专属:获取所有引用的图片 |
Page.insert_image() | PDF 专属:插入图片 |
Page.replace_image() | PDF 专属:替换图片 |
Page.get_links() | 获取所有链接 |
Page.insert_link() | PDF 专属:插入链接 |
Page.update_link() | PDF 专属:修改链接 |
页面属性
属性 | 描述 |
---|---|
Page.rect | 页面矩形边界 |
Page.bound() | 页面矩形边界(受旋转影响) |
Page.rotation | PDF 专属:页面旋转角度 |
Page.mediabox | 页面 /MediaBox |
Page.cropbox | 页面裁剪框 |
Page.trimbox | 页面 /TrimBox |
Page.rotation_matrix | PDF 专属:获取旋转后坐标 |
Page.derotation_matrix | PDF 专属:获取未旋转坐标 |
Page类方法详解
bound()
确定页面的矩形区域。与属性 Page.rect
相同。对于 PDF 文档,这通常也与 mediabox 和 cropbox 一致,但并非总是如此。例如,如果页面被旋转,此方法的返回值会反映这一点,而 Page.cropbox
不会发生变化。
返回类型:
Rect
add_caret_annot(point)
仅适用于 PDF:在页面上添加 插入符号(caret) 图标。Caret 注释是一种可视化符号,通常用于指示页面上存在文本编辑。
参数:
point (point_like)
—— 20×20 像素矩形 的左上角坐标,矩形内包含 MuPDF 提供的图标。
返回类型:
Annot
返回值:
返回创建的注释对象。该注释的描边颜色为 蓝色 (0, 0, 1),不支持填充颜色。
注意:新增于 v1.16.0
add_text_annot(point, text, icon='Note')
仅适用于 PDF:在页面上添加一个 评论图标(“便签”) 并附带文本。只有图标可见,文本是隐藏的,许多 PDF 查看器可以通过 鼠标悬停 在符号上显示文本内容。
参数:
point (point_like)
—— 20×20 像素矩形 的左上角坐标,矩形内包含 MuPDF 提供的 “Note” 图标。text (str)
—— 注释文本,双击 或 悬停 图标时会显示。支持任何拉丁字符。icon (str)
—— 选择注释图标,默认值为 “Note”,可选值包括:"Note"
(默认)"Comment"
"Help"
"Insert"
"Key"
"NewParagraph"
"Paragraph"
(新增于 v1.16.0)
返回类型:
Annot
返回值:
返回创建的注释对象。描边颜色为 黄色 (1, 1, 0),不支持填充颜色。
add_freetext_annot(rect, text, ...)
仅适用于 PDF:在指定的矩形区域内添加文本。可以选择 气泡注释(callout) 形式,并提供多个参数自定义外观。
参数:
rect (rect_like)
—— 矩形区域,文本将在此区域内自动换行,超出区域的部分将 不可见 且 无警告。text (str)
—— 插入的文本,支持:- 拉丁字符
- 希腊字符
- 俄语字符
- 中日韩字符
若richtext=True
,则文本会被解析为 HTML 语法,支持丰富的文本格式。
fontsize (float)
—— 字体大小,默认值 11(若richtext=True
则忽略)。fontname (str)
—— 字体名称,默认 Helvetica (Helv)。支持:"Helv"
(Helvetica)"Cour"
(Courier)"TiRo"
(Times-Roman)"ZaDb"
(ZapfDingBats)"Symb"
(Symbol)(仅支持标准字体,不支持加粗或斜体)
text_color (list/tuple/float)
—— 文本颜色,默认值 黑色 (0, 0, 0)(若richtext=True
则忽略)。fill_color (list/tuple/float)
—— 填充颜色(仅影响矩形区域或气泡注释的终点),默认None
。border_color (list/tuple/float)
—— 仅当richtext=True
时生效,否则使用text_color
。border_width (float)
—— 边框和气泡注释的线条宽度,默认 0(无边框)。dashes (list/tuple)
—— 设定 虚线样式(默认