Python图片转换PDF:专业指南与代码实现
Python图片转换PDF:专业指南与代码实现
在日常工作中,我们经常需要将多张图片合并成一个PDF文件,以便于存储、分享或打印。Python提供了多种库和方法来实现图片到PDF的转换,从简单的脚本到复杂的自动化流程,都能高效完成。本文将详细介绍几种常用方法,并提供可运行的代码示例。
为什么选择Python进行图片转PDF?
Python作为一门通用编程语言,拥有丰富的第三方库生态系统,特别适合处理文件转换任务。使用Python进行图片转PDF的优势包括:
- 自动化能力:可以轻松实现批量处理,减少手动操作
- 跨平台:在Windows、macOS和Linux上均可运行
- 可定制性:可以根据需求调整PDF参数,如页面大小、图片位置和压缩设置
- 集成方便:易于与其他Python脚本或系统集成
方法一:使用img2pdf库(推荐)
img2pdf是一个专门用于将图片转换为PDF的Python库,它能直接将图片嵌入PDF而不重新编码,保持原始质量。
安装与基本用法
# 安装img2pdf
pip install img2pdf
# 基本转换代码
import img2pdf
from pathlib import Path
def images_to_pdf(image_list, output_path):
"""将图片列表转换为单个PDF文件"""
with open(output_path, "wb") as f:
f.write(img2pdf.convert(image_list))
print(f"PDF已生成:{output_path}")
# 使用示例
image_files = ["image1.jpg", "image2.png", "image3.jpeg"]
images_to_pdf(image_files, "output.pdf")
处理文件夹中的图片
可以使用pathlib模块处理整个文件夹中的图片:
from pathlib import Path
import img2pdf
def batch_convert(folder_path, output_pdf):
"""转换文件夹中的所有图片为PDF"""
folder = Path(folder_path)
image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.tiff'}
# 收集图片文件并按名称排序
images = sorted(
[f for f in folder.iterdir()
if f.suffix.lower() in image_extensions],
key=lambda x: x.name
)
if not images:
print("未找到图片文件")
return
# 转换并保存
with open(output_pdf, "wb") as f:
f.write(img2pdf.convert([str(img) for img in images]))
print(f"成功将{len(images)}张图片转换为PDF:{output_pdf}")
# 使用示例
batch_convert("./images_folder", "all_images.pdf")
方法二:使用Pillow(PIL)库
Pillow是Python的图像处理库,也可以用来创建PDF文件。这种方法适合需要额外图像处理的情况。
from PIL import Image
from pathlib import Path
def pillow_images_to_pdf(image_files, output_path):
"""使用Pillow将图片转换为PDF"""
# 打开第一张图片作为基础
first_img = Image.open(image_files[0])
# 转换为RGB模式(PDF需要RGB)
if first_img.mode != "RGB":
first_img = first_img.convert("RGB")
# 创建其他图片列表
other_images = []
for img_path in image_files[1:]:
img = Image.open(img_path)
if img.mode != "RGB":
img = img.convert("RGB")
other_images.append(img)
# 保存为PDF
first_img.save(
output_path,
"PDF",
resolution=100.0,
save_all=True,
append_images=other_images
)
print(f"PDF已生成:{output_path}")
# 使用示例
image_list = ["img1.png", "img2.jpg", "img3.bmp"]
pillow_images_to_pdf(image_list, "pillow_output.pdf")
方法三:使用ReportLab库(高级控制)
ReportLab是专业的PDF生成库,提供最精细的控制,适合需要复杂布局的场景。
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas
from PIL import Image
import os
def reportlab_images_to_pdf(image_files, output_path, page_size=letter):
"""使用ReportLab创建带图片的PDF"""
c = canvas.Canvas(output_path, pagesize=page_size)
width, height = page_size
for img_path in image_files:
# 获取图片尺寸
with Image.open(img_path) as img:
img_width, img_height = img.size
# 计算缩放比例以适应页面
ratio = min(width / img_width, height / img_height)
new_width = img_width * ratio
new_height = img_height * ratio
# 居中放置
x = (width - new_width) / 2
y = (height - new_height) / 2
# 绘制图片
c.drawImage(img_path, x, y, width=new_width, height=new_height)
c.showPage()
c.save()
print(f"PDF已生成:{output_path}")
# 使用示例
images = ["photo1.jpg", "photo2.png"]
reportlab_images_to_pdf(images, "reportlab_output.pdf")
高级功能与优化
1. 图片排序与过滤
在实际应用中,图片可能需要按特定规则排序:
import re
from pathlib import Path
def natural_sort_key(path):
"""自然排序键函数"""
name = path.stem
return [
int(part) if part.isdigit() else part.lower()
for part in re.split(r'([0-9]+)', name)
]
# 使用自然排序
images = sorted(Path("./images").glob("*.jpg"), key=natural_sort_key)
2. PDF压缩优化
转换时可以考虑压缩选项,减小文件体积:
import img2pdf
def compress_images_to_pdf(image_files, output_path, dpi=150):
"""带压缩的转换"""
# img2pdf默认保持原始分辨率
# 可以先调整图片大小再转换
with img2pdf.open("rb", [open(f, "rb").read() for f in image_files]) as doc:
doc.save(output_path, compress=True)
3. 错误处理与验证
生产环境中需要添加完善的错误处理:
from pathlib import Path
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def safe_images_to_pdf(image_files, output_path):
"""带错误处理的安全转换"""
valid_images = []
for img_path in image_files:
try:
path = Path(img_path)
if path.exists() and path.is_file():
# 验证文件是否为有效图片
with Image.open(path) as img:
img.verify()
valid_images.append(str(path))
else:
logger.warning(f"文件不存在或不是有效文件:{img_path}")
except Exception as e:
logger.error(f"验证图片失败 {img_path}: {str(e)}")
if not valid_images:
logger.error("没有有效的图片文件")
return False
try:
images_to_pdf(valid_images, output_path)
return True
except Exception as e:
logger.error(f"生成PDF失败:{str(e)}")
return False
完整示例:图片转PDF命令行工具
以下是一个完整的命令行工具示例,集成了多种功能:
#!/usr/bin/env python3
"""图片转PDF命令行工具"""
import argparse
from pathlib import Path
import img2pdf
from PIL import Image
def main():
parser = argparse.ArgumentParser(description="将图片转换为PDF文件")
parser.add_argument("images", nargs="+", help="图片文件路径")
parser.add_argument("-o", "--output", default="output.pdf", help="输出PDF文件名")
parser.add_argument("-r", "--recursive", action="store_true", help="递归搜索子文件夹")
parser.add_argument("-s", "--sort", choices=["name", "date", "size"],
default="name", help="图片排序方式")
args = parser.parse_args()
# 收集图片文件
image_files = []
for img in args.images:
path = Path(img)
if path.is_dir():
pattern = "**/*.jpg" if args.recursive else "*.jpg"
for ext in ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.tiff"]:
image_files.extend(path.glob(pattern.replace("*.jpg", ext)))
elif path.is_file():
image_files.append(path)
# 排序
if args.sort == "name":
image_files.sort(key=lambda x: x.name.lower())
elif args.sort == "date":
image_files.sort(key=lambda x: x.stat().st_mtime)
elif args.sort == "size":
image_files.sort(key=lambda x: x.stat().st_size)
# 转换
try:
with open(args.output, "wb") as f:
f.write(img2pdf.convert([str(img) for img in image_files]))
print(f"成功生成PDF:{args.output},包含{len(image_files)}张图片")
except Exception as e:
print(f"转换失败:{str(e)}")
return 1
return 0
if __name__ == "__main__":
exit(main())
总结
使用Python将图片转换为PDF是一个简单而强大的解决方案。根据具体需求选择合适的库:
- img2pdf:最简单直接,保持原始质量,适合大多数情况
- Pillow:当需要图像预处理时使用
- ReportLab:需要复杂PDF布局时的首选
通过掌握这些方法,你可以轻松创建自动化脚本,处理从日常文档扫描到专业图像归档的各种任务。记住在生产环境中添加适当的错误处理和日志记录,以确保脚本的健壮性。