Python图片转PDF:高效实现多图合并与自定义布局

在日常办公或数据处理中,我们经常需要将多张图片(如扫描件、截图、照片等)合并为一个PDF文件,方便分享或归档。虽然市面上有很多工具可以完成这一任务,但通过Python脚本实现不仅灵活可控,还能根据需求定制布局(如横向/纵向、纸张大小等)。本文将介绍如何使用Python的FPDFPillow库高效实现图片转PDF,并支持中文参数和错误处理。


一、核心功能需求

在开发图片转PDF工具时,通常需要满足以下需求:

  1. 多图合并:支持将多张图片合并为一个PDF。
  2. 自定义布局
    • 支持横向或纵向页面方向。
    • 支持标准纸张大小(如A4、A3)或自定义尺寸。
  3. 图片自适应:图片按比例缩放以适应页面,避免变形。
  4. 错误处理:跳过损坏的图片,保证程序稳定性。
  5. 中文友好:参数支持中文(如"纵向"、"横向")。

二、技术选型

  • FPDF:轻量级PDF生成库,支持自定义页面尺寸和图片插入。
  • Pillow(PIL):图片处理库,用于获取图片尺寸和格式转换。
  • glob:文件路径匹配,方便批量读取图片。

三、完整代码实现

以下是支持中文参数、自定义布局和错误处理的完整代码:

python 复制代码
import os
import glob
from fpdf import FPDF
from PIL import Image

def images_to_pdf_fpdf(
    image_paths, 
    output_pdf_path, 
    paper_size="A4",  # 纸张大小(默认A4)
    direction="纵向"   # 布局方向(默认纵向,支持"横向")
):
    """
    将多张图片合并为PDF,支持自定义纸张大小和方向(纵向/横向)
    
    参数:
        image_paths: 图片路径列表(支持通配符,如 '*.jpg')
        output_pdf_path: 输出PDF路径
        paper_size: 纸张大小(默认'A4',支持'A3'/'Letter'/'Legal'或自定义元组,如(200, 300))
        direction: 布局方向(默认'纵向',可选'横向')
    """
    # 定义标准纸张尺寸(单位:毫米)
    paper_sizes = {
        "A4": (210, 297),
        "A3": (297, 420),
        "Letter": (215.9, 279.4),
        "Legal": (215.9, 355.6),
    }

    # 校验纸张大小参数
    if isinstance(paper_size, str):
        if paper_size.upper() in paper_sizes:
            width_mm, height_mm = paper_sizes[paper_size.upper()]
        else:
            raise ValueError(f"未知的纸张大小: {paper_size}。支持的值: {list(paper_sizes.keys())} 或自定义元组(如 (200, 300))")
    elif isinstance(paper_size, (tuple, list)) and len(paper_size) == 2:
        width_mm, height_mm = paper_size
    else:
        raise ValueError("paper_size 必须是预定义名称(如 'A4')或 (width_mm, height_mm) 元组")

    # 校验方向参数
    direction = direction.lower()
    if direction not in ["纵向", "横向"]:
        raise ValueError("direction 必须是 '纵向' 或 '横向'")

    # 根据方向调整宽高(横向时交换宽高)
    if direction == "横向":
        width_mm, height_mm = height_mm, width_mm

    # 创建 PDF 对象
    pdf = FPDF(unit="mm", format=(width_mm, height_mm))  # 直接传入宽高

    for image_path in image_paths:
        try:
            # 打开图片并获取尺寸(转换为毫米)
            img = Image.open(image_path)
            img_width, img_height = img.size
            img_width_mm = img_width * 0.264583  # 像素 → 毫米(1像素 ≈ 0.264583毫米)
            img_height_mm = img_height * 0.264583

            # 计算缩放比例(适应当前页面尺寸)
            scale_width = width_mm / img_width_mm
            scale_height = height_mm / img_height_mm
            scale = min(scale_width, scale_height)

            # 计算缩放后的图片尺寸
            new_width_mm = img_width_mm * scale
            new_height_mm = img_height_mm * scale

            # 添加页面并插入图片(居中)
            pdf.add_page()
            x = (width_mm - new_width_mm) / 2
            y = (height_mm - new_height_mm) / 2
            pdf.image(image_path, x=x, y=y, w=new_width_mm, h=new_height_mm)

        except Exception as e:
            print(f"警告:图片 {image_path} 处理失败,跳过。错误: {e}")

    # 保存 PDF
    pdf.output(output_pdf_path)
    print(f"PDF 已生成:{output_pdf_path}")

# 示例用法
if __name__ == "__main__":
    # 获取所有JPG图片(使用raw字符串避免转义)
    image_paths = glob.glob(r'E:\Python\learning\图片转PDF\img\*流水.jpg')
    output_pdf_path = "1-3月银行流水.pdf"

    # 调用方式1:默认A4纵向
    images_to_pdf_fpdf(image_paths, output_pdf_path)

    # 调用方式2:A4横向
    images_to_pdf_fpdf(image_paths, output_pdf_path, paper_size="A4", direction="横向")

    # 调用方式3:自定义纸张大小(200x300毫米)纵向
    images_to_pdf_fpdf(image_paths, output_pdf_path, paper_size=(200, 300), direction="纵向")

四、代码解析

1. 纸张大小与方向处理

  • 标准纸张 :通过字典paper_sizes定义常见尺寸(如A4、A3)。
  • 自定义尺寸 :支持传入元组(如(200, 300))。
  • 方向调整 :横向时交换宽高(width_mm, height_mm = height_mm, width_mm)。

2. 图片自适应缩放

  • 像素转毫米:1像素 ≈ 0.264583毫米。
  • 缩放比例:取宽高缩放比例的最小值,确保图片完整显示。
  • 居中布局 :计算图片在页面中的偏移量(xy)。

3. 错误处理

  • 捕获单张图片处理时的异常(如损坏图片),打印警告并跳过。
  • 参数校验:检查paper_sizedirection的有效性。

4. 中文参数支持

  • 将方向参数命名为direction,接受"纵向""横向"
  • 内部统一转换为小写(direction.lower()),避免大小写敏感问题。

五、使用场景示例

需求 调用方式
默认A4纵向 images_to_pdf_fpdf(image_paths, output_pdf_path)
A4横向 images_to_pdf_fpdf(image_paths, output_pdf_path, direction="横向")
自定义200x300毫米纵向 images_to_pdf_fpdf(image_paths, output_pdf_path, paper_size=(200, 300), direction="纵向")

六、注意事项

  1. 图片方向
    • 代码仅调整PDF页面方向,不旋转图片内容 。如果图片本身是横向的,建议先用Pillow旋转图片(如img.rotate(90))。
  2. 路径问题
    • 使用glob.glob(r'...')(raw string)避免Windows路径转义错误。
  3. 性能优化
    • 对于大量图片,可考虑添加进度条(如tqdm库)。

七、总结

通过Python实现图片转PDF,不仅灵活高效,还能满足个性化需求(如自定义布局、错误处理等)。本文的代码支持中文参数、标准/自定义纸张大小和横向/纵向布局,适合办公自动化场景。你可以根据实际需求进一步扩展功能(如添加水印、调整图片质量等)。

完整代码与示例 已开源至GitHub:点击查看(示例链接需替换为实际仓库地址)。

希望这篇文章能帮助你轻松实现图片转PDF!如果有任何问题或建议,欢迎在评论区交流。 🚀

相关推荐
knight_9___10 小时前
RAG面试篇7
java·面试·agent·rag·智能体
song85460113410 小时前
idea问题解决
java·ide·intellij-idea
问水っ10 小时前
Qt高级编程 第7章 用QtConcurrent实现线程处理
java·开发语言
SimonKing10 小时前
AI编程工具装了一大堆,Skills 管理乱成粥?这个开源神器一招搞定!
java·后端·程序员
one_love_zfl10 小时前
java面试-微服务篇
java·微服务·面试
郝学胜-神的一滴10 小时前
系统设计:新鲜事系统扩展与优化
java·python·职场和发展·php·软件工程·软件构建
思绪无限10 小时前
YOLOv5至YOLOv12升级:零售柜商品检测软件的设计与实现(完整代码+界面+数据集项目)
人工智能·python·深度学习·目标检测·计算机视觉·零售柜商品检测·yolov12
优化控制仿真模型10 小时前
【26年最新】新大纲普通话考试真题题库50套(PDF电子版)
经验分享·pdf
爱吃烤鸡翅的酸菜鱼10 小时前
Maven中BOM(Bill of Materials)的使用详解
java·中间件·maven·源代码管理
zl_dfq10 小时前
Python学习6 之 【Lambda表达式、列表与元组、推导式】
python