Python PDF神器PyMuPDF使用指南 (三)——图像和注释功能

系列文章:

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.pngpage-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,整数)进行标识。如果你知道这个编号,有两种方法可以访问图像的数据:

  1. 使用指令 pix = pymupdf.Pixmap(doc, xref) 创建图像的Pixmap。这种方法非常快速(仅需几微秒)。生成的pixmap属性(宽度、高度等)将反映图像的属性。在这种情况下ÿ
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塞大花

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值