系列文章:
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处理PDF(和其他)文档的图像处理和注释处理功能。
图片处理
如何从文档页面生成图片
这个简单的脚本将从文档文件生成每一页的 PNG 文件。文档可以是任何支持的类型。
该脚本作为命令行工具运行,期待传入文件名作为参数。生成的图片文件(每页一个)将保存在脚本所在的目录:
import sys, pymupdf # 导入绑定
fname = sys.argv[1] # 从命令行获取文件名
doc = pymupdf.open(fname) # 打开文档
for page in doc: # 遍历页面
pix = page.get_pixmap() # 渲染页面为图片
pix.save("page-%i.png" % page.number) # 将图片保存为PNG
现在,脚本目录中将包含名为 page-0.png
、page-1.png
等的 PNG 图片文件。图片的尺寸与页面相同,宽度和高度四舍五入为整数,例如 A4 纵向页面为 595 x 842 像素。它们的分辨率为 96 dpi,在 x 和 y 方向上都没有透明度。可以更改这些设置,如何修改将在接下来的章节中讨论。
如何增加图像分辨率
文档页面的图像由 Pixmap 表示,创建 Pixmap 的最简单方法是通过 Page.get_pixmap()
方法。
该方法有很多选项可以影响结果,其中最重要的是 Matrix
,它可以让你放大、旋转、扭曲或镜像结果。
默认情况下,Page.get_pixmap()
会使用身份矩阵(Identity matrix),即不做任何改变。
接下来,我们将每个维度的缩放因子设置为 2,这将生成一个分辨率提升四倍的图像(同时图像大小也会增加约四倍):
zoom_x = 2.0 # 水平缩放因子
zoom_y = 2.0 # 垂直缩放因子
mat = pymupdf.Matrix(zoom_x, zoom_y) # 每个维度的缩放因子为 2
pix = page.get_pixmap(matrix=mat) # 使用 'mat' 替代身份矩阵
从版本 1.19.2 起,有一种更直接的方法可以设置分辨率:可以使用 dpi
参数(每英寸点数),它可以替代 matrix
。要创建 300 dpi 的页面图像,可以这样指定:pix = page.get_pixmap(dpi=300)
。除了简化语法外,这种方法还有一个附加优点,就是 dpi 值会被保存到图像文件中,而使用 Matrix
方法时不会自动保存。
如何创建部分 Pixmaps(裁剪)
并不总是需要或希望获取整个页面的图像。例如,当你在 GUI 中显示图像时,可能只想显示页面的某一部分并放大它。
假设你的 GUI 窗口可以显示整个文档页面,但现在你想要填充窗口的右下角四分之一区域,同时使用更高的分辨率。
要实现这一点,可以定义一个矩形区域(clip),该区域为你希望在 GUI 中显示的部分。通过提供两个对角的角点来构造矩形是 PyMuPDF 中构造矩形的一种方法,这里我们就是这么做的。
mat = pymupdf.Matrix(2, 2) # 每个方向的缩放因子为 2
rect = page.rect # 页面矩形
mp = (rect.tl + rect.br) / 2 # 页面矩形的中点,作为裁剪的左上角
clip = pymupdf.Rect(mp, rect.br) # 你想要的区域
pix = page.get_pixmap(matrix=mat, clip=clip) # 获取该区域的 Pixmap
在上面的代码中,我们通过指定页面矩形的中点 mp
和其右下角 rect.br
来构造裁剪矩形(clip)。
如何将裁剪区域缩放到 GUI 窗口
请参考上一节。现在,我们希望计算一个裁剪区域的缩放因子,使得它的图像可以最佳适应给定的 GUI 窗口。这意味着图像的宽度或高度(或两者)将等于窗口的尺寸。以下代码片段需要你提供 GUI 窗口的 WIDTH
和 HEIGHT
,以及裁剪区域。
# WIDTH: GUI 窗口的宽度
# HEIGHT: GUI 窗口的高度
# clip: 文档页面的子矩形
# 比较图像和窗口的宽高比
if clip.width / clip.height < WIDTH / HEIGHT:
# 裁剪区域更窄:按窗口高度进行缩放
zoom = HEIGHT / clip.height
else: # 裁剪区域更宽:按窗口宽度进行缩放
zoom = WIDTH / clip.width
mat = pymupdf.Matrix(zoom, zoom)
pix = page.get_pixmap(matrix=mat, clip=clip) # 获取缩放后的 Pixmap
如果你已经有了缩放因子,并希望计算适配的裁剪区域,可以这样做:
width = WIDTH / zoom
height = HEIGHT / zoom
clip = pymupdf.Rect(tl, tl.x + width, tl.y + height)
# 确保裁剪区域仍然在页面内
clip &= page.rect
mat = pymupdf.Matrix(zoom, zoom)
pix = pymupdf.Pixmap(matrix=mat, clip=clip) # 获取缩放后的 Pixmap
如何创建或抑制注释图像
通常情况下,页面的 Pixmap 也会显示页面的注释。有时,这可能并不需要。
要在渲染的页面中抑制注释图像,只需在 Page.get_pixmap() 中指定 annots=False
。
你也可以单独渲染注释:它们有自己的 Annot.get_pixmap() 方法。返回的 Pixmap 将与注释矩形具有相同的尺寸。
如何提取图片:非 PDF 文档
与之前的部分不同,本节讨论提取文档中包含的图像,以便将它们显示为一部分页面内容。
如果你希望将文档中的图像恢复为原始文件或内存区域,基本上有两个选择:
1. 将文档转换为 PDF,然后使用仅限 PDF 的提取方法。这个代码片段将文档转换为 PDF:
pdfbytes = doc.convert_to_pdf() # 这是一个字节对象
pdf = pymupdf.open("pdf", pdfbytes) # 将其作为 PDF 文档打开
# 现在像操作 PDF 文档一样使用 'pdf'
2. 使用 Page.get_text()
方法,并指定 “dict” 参数。这适用于所有文档类型。它将提取页面上显示的所有文本和图像,并以 Python 字典的形式进行格式化。每个图像都将出现在一个图像块中,包含元数据和二进制图像数据。对于字典的结构,详情请参见 TextPage
。该方法对于 PDF 文件也同样适用。这样就创建了一个列出页面所有图像的列表:
d = page.get_text("dict")
blocks = d["blocks"] # 块字典的列表
imgblocks = [b for b in blocks if b["type"] == 1] # 过滤出图像块
pprint(imgblocks[0])
{'bbox': (100.0, 135.8769989013672, 300.0, 364.1230163574219),
'bpc': 8,
'colorspace': 3,
'ext': 'jpeg',
'height': 501,
'image': b'\xff\xd8\xff\xe0\x00\x10JFIF\...', # 注意:这是一个大数据!
'size': 80518,
'transform': (200.0, 0.0, -0.0, 228.2460174560547, 100.0, 135.8769989013672),
'type': 1,
'width': 439,
'xres': 96,
'yres': 96}
如何提取图片:PDF 文档
PDF文档 像PDF中的任何其他“对象”一样,图像通过交叉引用号(xref,整数)进行标识。如果你知道这个编号,有两种方法可以访问图像的数据:
- 使用指令
pix = pymupdf.Pixmap(doc, xref)
创建图像的Pixmap。这种方法非常快速(仅需几微秒)。生成的pixmap属性(宽度、高度等)将反映图像的属性。在这种情况下ÿ