PDF 解析

PDF 里取出来的图片为什么和页面看到的不一样

带透明度的图像可能以主图与软遮罩分别存储。下面用 Pillow 构造 RGBA PNG,再插入内存 PDF,盘点主图和 SMask。提取主图字节不等于得到完整透明效果,也不等于重建页面上的所有显示实例。

阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。 这篇先解决哪一个问题 带透明度的图像可能以主图与软遮罩分别存储。下面用 Pillow 构造 RGBA PNG,再插入内存 PDF,盘点主图和 SMask。提取主图字节不等于得到完整透明效果,也不等于重建页面上的所有显示实例。 自包含的合成示例 依赖见导入列表。代码在内存中构造输入;运行记录单独提供,不代表对所有真实文件的保证。 from io import BytesIO from PIL import Image import pymupdf im = Image.new("RGBA", (16, 16), (255, 0, 0, 128)) raw = BytesIO() im.save(raw, format="PNG") with pymupdf.open() as doc: page = doc.new_page(width=100, height=100) page.insert_image(pymupdf.Rect(10, 10, 70, 70), stream=raw.getvalue()) images = page.get_images(full=True) assert len(images) == 1 xref, smask = images[0][:2] assert xref > 0 and smask > 0 assert doc.extract_image(xref)["width"] == 16 assert doc.extract_image(smask)["image"] PDF 里取出来的图片为什么和页面看到的不一样 当你用脚本从 PDF 中提取图片时,最常遇到的困惑是:提取出的文件要么是一片漆黑、尺寸怪异,要么干脆缺少了页面上明明存在的背景或水印。这通常不是代码写错了,而是因为你直接读取了 PDF 内部的原始图像对象(XRef),却忽略了页面渲染管线中的合成指令。PDF 规范中,图像存储与页面呈现是两个解耦的层级,原始对象往往只是最终视觉效果的一个组件。理解这一差异,是进行高质量文档解析、OCR 预处理或内容重组的前提。 原始对象与渲染管线的本质区别 PDF 文件结构像是一个资源仓库, Document.extract_image(xref) 这类方法只是把仓库里的零件原封不动地搬出来。但在页面上,这些零件经过了变换矩阵(CTM)缩放、裁剪路径(Clip Path)切割、透明度组(Transparency Group)混合以及软遮罩(Soft Mask)叠加。最典型的差异来自 SMask(软遮罩):许多带透明通道的 PNG 在 PDF 内部被拆分为一个 RGB 图像流和一个独立的 Gray 遮罩流。如果你只提取了主图像而丢弃了关联的 SMask 对象,得到的就是一张没有透明度的纯色矩形,原本透明的区域会变成黑色或白色。此外,为了节省体积,同一张高分辨率底图可能被多个页面复用,但每个页面通过不同的 /BBox 和矩阵只显示其局部区域;直接提取则会得到完整的大图,而非用户看到的裁切片段。这种“所见非所得”是 PDF 作为交换格式的固有特性,而非解析库的缺陷。 合成测试环境与边界情况处理 为了在不依赖外部文件的情况下验证提取逻辑,我们必须构建一个包含 SMask 的合成 PDF。以下代码使用 PyMuPDF 在内存中创建一个测试文档,其中包含一个带独立软遮罩的图像对象。这模拟了真实场景中“图标有透明背景但底层存储为分离流”的情况。 正确输出预期 :程序应能识别出图像关联了 SMask,并成功提取主图数据。 PyMuPDF 图像提取与遮罩关联校验 以下 Python 代码完全自包含,无需任何外部输入文件。它在内存中合成一个带 SMask 的 PDF,然后验证提取逻辑是否能正确识别遮罩关联。代码包含两个关键断言:一个验证正常提取的数据完整性,另一个验证对 SMask 关联状态的准确感知。 此代码聚焦于 元数据层面的完整性校验 。在实际生产中,若 smask_xref != 0 ,你需要使用 Pillow 等库将 doc.extract_image(smask_xref) 的结果作为 Alpha 通道粘贴到主图上。两个断言分别覆盖了“数据可提取”和“遮罩关联可见”这两个核心契约,防止在空文档或API变更时产生虚假成功。 提取结果验收与人工审查界限 自动化提取永远无法完全替代视觉确认。下表总结了常见的异常表现及其处置策略,帮助区分哪些是代码可修复的工程问题,哪些必须交给人工判断。 观察现象 可能原因 自动化处理决定 人工审查触发条件 图片全黑或全白 SMask 被当作独立图像提取;色彩空间解码失败 检查 smask 关联;尝试回退色彩空间 回退后仍无法辨识内容;涉及专色/设备相关颜色 图片方向颠倒/拉伸 CTM 矩阵包含负值缩放或非均匀变换 读取矩阵参数进行几何校正 校正后文字/人脸明显变形;复杂矢量裁剪路径 多张小图拼成一张大图 分块编码(Tiling Pattern)或条带化存储 按 BBox 坐标裁切或拼接 拼接缝隙明显;逻辑上应为独立语义单元 提取成功但页面不可见 被 OCG(可选内容组)隐藏;位于裁剪区外 查询 OCG 状态过滤;比对 CropBox 图层逻辑复杂(如嵌套OCMD);动态表单字段 分辨率极低/模糊 原始嵌入即为低清缩略图 记录 DPI 元数据,标记为低质 关键图表/文字因模糊不可读;需重新扫描源文件 请注意,“代码演示”仅验证 API 调用和数据流的连通性,不等于“端到端效果”达标。当遇到 OCG 嵌套逻辑、自定义着色器或加密文档时,脚本的输出仅供参考,必须以 PDF 阅读器的实际渲染为验收基准。 将这份检查清单用于文档翻译 先把页面顺序、来源位置与文本完整性检查清楚,再把同一份脱敏样本交给翻译流程。译后仍要检查标题、正文和图注是否正确对应,不能只看文字是否通顺。 OmniDoc(产品入口) 提供多格式文档翻译入口,官网介绍了 OCR、术语表与双语对照功能。对希望直接从文件开始处理的团队,这是一条值得用实际样本评估的路径。请使用有权上传的脱敏文件,并用本篇的检查项复核结果;这里不声称 OmniDoc 使用了本文的开源库或内部算法,也不以示例代替产品性能测试。 原厂接口依据: PyMuPDF 文档 。 - 1 -
更新于 2026-10-08