推荐用pil校验图片后,fitz显式设定页面尺寸并insert_image插入,避免insert_pdf或save(format="pdf");注意unicode路径用pathlib、大图缩放、ocr需额外处理。

用 PIL + fitz(PyMuPDF)合并图片为单页 PDF
直接用 PIL.Image.save(..., format="PDF") 虽然能转单张图,但批量时每张图会生成独立 PDF,无法合并在一个文档里;而 fitz 支持逐页插入图像,且保留原始分辨率和色彩空间,是真正可控的方案。
实操建议:
- 先用
PIL统一加载并校验图片(避免损坏文件中断流程),例如:Image.open(path).convert("RGB") - 用
fitz.Rect显式设定页面尺寸,防止自动缩放失真;推荐按图片原始width × height创建等大页面 - 插入时用
page.insert_image(rect, pixmap=...),别用insert_pdf——后者只接受 PDF 源,不支持图像对象
处理含中文路径或文件名时报 UnicodeEncodeError
错误常出现在 os.listdir() 或 open() 阶段,尤其 Windows 默认编码为 mbcs,而 Python 3 的 os 模块底层调用仍可能触发编码 fallback 失败。
绕过方式:
- 改用
pathlib.Path构造路径,它对 Unicode 更鲁棒:list(Path(".").glob("*.jpg")) - 读取图片时始终用
Image.open(str(p)),显式转为字符串而非依赖__fspath__行为 - 如果必须用
glob,加encoding="utf-8"参数(仅限io.open类操作,os模块本身不支持该参数,需换库)
PDF 文字层为空,但需要 OCR 后可检索
纯图像 PDF 默认没有文字层,fitz 插入的也是位图,pdfplumber 或 PyPDF2 读不出任何文本。要可检索,必须走 OCR 流程。
轻量级落地做法:
- 用
pytesseract.image_to_pdf直接输出带文字层的 PDF(要求系统已装 Tesseract,且语言包完整) - 若图片质量差,先用
cv2做二值化或去噪:cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) - OCR 后的 PDF 页面尺寸可能错乱,需在
pytesseract中传config='--psm 6'并手动指定pdf_options={"page-width": w, "page-height": h}
大图(如扫描件 >10MB)导致内存溢出或生成失败
PIL 加载高分辨率 TIFF/JPEG 时会解压成全尺寸 RGB 内存数组,一张 8000×12000 图像就占约 288MB;fitz 的 pixmap 构造也会复现该问题。
缓解策略:
- 加载前用
Image.open().size判断尺寸,超阈值(如 6000px 边长)则先缩放:img.thumbnail((6000, 6000), Image.LANCZOS) - 不用
Image.save(..., format="PDF")中间落盘,那会产生临时文件且不控质量;改用io.BytesIO在内存流转 - 生成 PDF 后立即调用
doc.save(..., garbage=4, deflate=True)压缩对象流,减少体积 30–70%
真正难的是平衡 OCR 准确率与内存占用——高 DPI 输入提升识别率,却让内存翻倍;实际中往往要在 200–300 DPI 之间做取舍,而不是无脑用原图分辨率。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











