基于PyMuPDF与ReportLab的PDF图片双向转换工具
概述
在日常工作中,我们经常需要在PDF与图片格式间进行转换,例如将PDF每页导出为图片进行编辑,或将一组图片合并成一个PDF文档。本文介绍一个用Python实现的双向转换工具,它不仅提供了命令行脚本,还封装了基于Tkinter的图形界面,支持批量处理与画质选择。
依赖库
主要依赖:
- PyMuPDF (fitz):用于解析PDF并渲染页面为图像。
- Pillow (PIL):辅助处理图片尺寸。
- ReportLab:将图片按序写入PDF。
- Tkinter:构建桌面交互界面。
安装命令:
pip install pymupdf pillow reportlab
核心转换逻辑
以下代码展示PDF转图片的功能,通过缩放矩阵控制输出分辨率:
import fitz
import os
def export_pages_to_image(file_path, scale=2.0):
doc = fitz.open(file_path)
base = os.path.splitext(os.path.basename(file_path))[0]
out_dir = os.path.join(os.path.dirname(file_path), f"{base}_images")
os.makedirs(out_dir, exist_ok=True)
for idx in range(len(doc)):
page = doc[idx]
matrix = fitz.Matrix(scale, scale)
pixmap = page.get_pixmap(matrix=matrix)
dest = os.path.join(out_dir, f"page_{idx+1:04d}.png")
pixmap.save(dest)
print(f"Exported page {idx+1} -> {dest}")
doc.close()
return out_dir
图片合并回PDF时,使用ReportLab按比例将图片填充至页面:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from PIL import Image
import os
def compile_images_to_pdf(image_dir, output_path):
valid_files = sorted(
[f for f in os.listdir(image_dir) if f.lower().endswith(('.png', '.jpg', '.jpeg'))]
)
if not valid_files:
raise FileNotFoundError("目录中没有可用的图片文件")
c = canvas.Canvas(output_path, pagesize=A4)
page_w, page_h = A4
for img_file in valid_files:
img_path = os.path.join(image_dir, img_file)
with Image.open(img_path) as im:
im_w, im_h = im.size
factor = min(page_w / im_w, page_h / im_h)
scaled_w = im_w * factor
scaled_h = im_h * factor
# 居中对齐
x = (page_w - scaled_w) / 2
y = (page_h - scaled_h) / 2
c.drawImage(img_path, x, y, width=scaled_w, height=scaled_h)
c.showPage()
c.save()
print(f"PDF已生成:{output_path}")
图形界面实现
使用Tkinter的Notebook组件制作双标签页,分别对应"PDF转图片"和"图片转PDF"。用户可浏览文件/目录、选择画质(标清/高清/超清),并通过进度条与日志区域获得实时反馈。
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import threading
class ConverterApp(tk.Tk):
def __init__(self):
super().__init__()
self.title("PDF与图片互转工具")
self.geometry("600x450")
self._init_ui()
def _init_ui(self):
self.notebook = ttk.Notebook(self)
self.tab1 = ttk.Frame(self.notebook)
self.tab2 = ttk.Frame(self.notebook)
self.notebook.add(self.tab1, text="PDF → 图片")
self.notebook.add(self.tab2, text="图片 → PDF")
self.notebook.pack(expand=True, fill="both")
self._build_pdf_to_image_tab()
self._build_image_to_pdf_tab()
def _build_pdf_to_image_tab(self):
# 文件选择、输出目录、画质下拉框、进度条、日志
# 绑定转换函数,运行在独立线程中避免阻塞UI
pass
def _build_image_to_pdf_tab(self):
# 类似结构
pass
def _start_conversion(self, target, **kwargs):
thread = threading.Thread(target=target, kwargs=kwargs)
thread.daemon = True
thread.start()
if __name__ == "__main__":
ConverterApp().mainloop()
(完整界面逻辑省略,实际代码包含文件浏览、参数收集与进度回调等功能。)
使用说明
- 选择PDF文件并指定图片输出目录,设置所需画质后点击"转换"。
- 图片转PDF时,选择存放图片的文件夹,自动生成以时间戳命名的输出PDF。
- 所有操作均有进度提示,转换完成后弹出通知。
封装与分发
可以使用PyInstaller将整个应用打包为独立的exe文件,方便无Python环境的用户使用:
pyinstaller --onefile --windowed converter.py