使用 Python 改变 PDF 页面大小

1 阅读9分钟

在处理 PDF 文档时,经常需要调整页面尺寸以适应不同的打印需求、显示设备或归档标准。无论是将 A4 文档转换为 Letter 尺寸、创建自定义大小的报告,还是批量调整扫描文档的页面比例,掌握 PDF 页面大小调整技术都能显著提升工作效率。本文将深入探讨如何使用 Python 实现多种场景下的 PDF 页面大小调整功能。

为什么需要改变 PDF 页面大小

在文档处理和出版工作流程中,调整 PDF 页面尺寸有着广泛的应用:

  • 打印适配:将文档调整为特定打印机支持的纸张尺寸(如 A4、Letter、Legal)
  • 标准化归档:统一文档尺寸以符合行业或机构标准
  • 设备优化:为平板电脑、手机等移动设备优化页面大小
  • 演示准备:创建适合投影仪或大屏幕显示的宽屏格式
  • 印刷出版:调整页面尺寸以匹配印刷规格和装订要求

通过 Python 自动化这一过程,可以实现批量处理、精确控制尺寸参数和集成到更大的文档管理工作流中。

环境准备

在开始之前,需要安装支持 PDF 操作的 Python 库。Spire.PDF for Python 提供了全面的 API 来处理 PDF 文档的页面设置和尺寸调整功能。

pip install Spire.PDF

安装完成后,在 Python 脚本中导入相关模块即可开始工作:

from spire.pdf import *
from spire.pdf.common import *

基础页面尺寸调整

改变 PDF 页面大小的核心思路是创建一个新文档,按照目标尺寸添加页面,然后将原页面内容复制到新页面中。以下是最基础的等比例缩放示例:

当需要将整个 PDF 文档的页面按固定比例缩小时,最稳定的方式是重新定义目标页面的尺寸并配合 PdfTextLayout 的自动布局功能。这种方法通过设置 PdfLayoutType.OnePage,让程序自动将原始页面内容作为模板,等比例地“填充”到缩小后的新页面容器中,从而避免了手动计算复杂的矩阵变换和坐标偏移。

from spire.pdf import *
from spire.pdf.common import *

# 初始化文件路径
inputFile = "E:/Administrator/Python1/input/AI绘画的利与弊.pdf"
outputFile = "E:/Administrator/Python1/output/缩小版文档.pdf"

# 加载原始文档并创建目标文档对象
originalPdf = PdfDocument()
originalPdf.LoadFromFile(inputFile)
newPdf = PdfDocument()

# 设置全局缩放比例(0.8 表示 80%)
scale = 0.8

# 循环处理每一页:计算新尺寸并重新绘制
for i in range(originalPdf.Pages.Count):
    page = originalPdf.Pages.get_Item(i)
    
    # 计算缩放后的目标宽高
    target_width = float(page.Size.Width * scale)
    target_height = float(page.Size.Height * scale)
    
    # 在新文档中添加匹配缩放尺寸的页面,边距设为 0.0
    newPage = newPdf.Pages.Add(SizeF(target_width, target_height), PdfMargins(0.0))
    
    # 配置布局模式为“单页填充”,确保内容自动适配新页面尺寸
    layout = PdfTextLayout()
    layout.Layout = PdfLayoutType.OnePage
    
    # 将原页内容转为模板,并绘制到新页面的起点 (0.0, 0.0)
    template = page.CreateTemplate()
    template.Draw(newPage, PointF(0.0, 0.0), layout)

# 保存结果并释放系统资源
newPdf.SaveToFile(outputFile)
newPdf.Close()
originalPdf.Close()

调整 PDF 页面大小.jpg

实现逻辑要点:

  • 容器适配:通过 newPdf.Pages.Add() 创建一个缩小后的物理纸张,这决定了最终 PDF 的外观尺寸。
  • 自动布局PdfLayoutType.OnePage 充当了“缩放引擎”,它会自动识别目标页面(newPage)的大小,并将源模板(template)按比例压缩至填满该页面。
  • 类型安全:在 Python 接口调用中,所有坐标和尺寸参数均显式使用 float 类型,以确保与底层图形库的兼容性。

转换为标准纸张尺寸

除了等比例缩放,你还可以将 PDF 页面转换为标准的纸张尺寸,如 B4、A3、Letter 等。这种转换常用于打印准备和文档标准化:

当需要将文档转换为特定标准尺寸时,可以使用 PdfPageSize 类提供的预定义尺寸。这种方法会创建固定尺寸的页面,可能需要调整内容的缩放比例或位置以适应新页面。这对于准备打印文件或符合组织文档标准非常有用:

from spire.pdf.common import *
from spire.pdf import *

# 明确源文件和输出文件路径
inputFile = "E:/Administrator/Python1/input/AI绘画的利与弊.pdf"
outputFile = "E:/Administrator/Python1/output/标准大小.pdf"

# 创建原始 PdfDocument 对象
originalPdf = PdfDocument()
# 加载待处理的 PDF 文件
originalPdf.LoadFromFile(inputFile)

# 创建新的 PdfDocument 对象
newPdf = PdfDocument()

# 遍历原始 PDF 文档中的每一页
for i in range(originalPdf.Pages.Count):
    # 获取当前页对象
    page = originalPdf.Pages.get_Item(i)
    
    # 创建新的页面,并设置页面大小为 B4,边距为 0
    newPage = newPdf.Pages.Add(PdfPageSize.B4(), PdfMargins(0.0))
    
    # 创建文本布局对象
    layout = PdfTextLayout()
    # 设置文本布局类型为单页
    layout.Layout = PdfLayoutType.OnePage
    
    # 创建模板对象
    template = page.CreateTemplate()
    # 在新页面上绘制模板内容,并应用文本布局
    template.Draw(newPage, PointF.Empty(), layout)

# 将修改后的PDF文档保存到指定路径
newPdf.SaveToFile(outputFile)
newPdf.Close()
originalPdf.Close()

调整 PDF 页面大小为 B4.jpg

PdfPageSize 类提供了多种预定义尺寸,包括 B4()B3()Letter()Legal()Tabloid() 等。通过计算原始尺寸与目标尺寸的比例,并选择较小的缩放因子,可以确保所有内容都能完整地适应新页面而不会被裁剪。

自定义页面尺寸

对于特殊需求,你可以完全自定义页面的宽度和高度,而不受标准尺寸限制:

在某些场景下,你可能需要创建非标准尺寸的 PDF,比如制作横幅、名片、海报或特殊装订的文档。这时可以直接指定具体的宽度和高度值(以点为单位,1 点 = 1/72 英寸)。这种灵活性让你能够精确控制输出文档的尺寸:

from spire.pdf import *
from spire.pdf.common import *

inputFile = "普通文档.pdf"
outputFile = "自定义宽版文档.pdf"

# 加载原始文档
originalDoc = PdfDocument()
originalDoc.LoadFromFile(inputFile)

# 创建自定义尺寸的文档
customWidth = 800.0  # 点单位
customHeight = 400.0  # 点单位

with PdfDocument() as newDoc:
    for i in range(originalDoc.Pages.Count):
        page = originalDoc.Pages.get_Item(i)
        
        # 计算缩放比例
        scaleX = customWidth / page.Size.Width
        scaleY = customHeight / page.Size.Height
        scale = min(scaleX, scaleY)
        
        # 添加自定义尺寸的页面
        margins = PdfMargins(0.0)
        newPage = newDoc.Pages.Add(SizeF(customWidth, customHeight), margins)
        
        # 可选:居中内容
        offsetX = (customWidth - page.Size.Width * scale) / 2
        offsetY = (customHeight - page.Size.Height * scale) / 2
        
        # 应用平移和缩放变换
        newPage.Canvas.TranslateTransform(offsetX, offsetY)
        newPage.Canvas.ScaleTransform(scale, scale)
        
        # 复制内容
        newPage.Canvas.DrawTemplate(page.CreateTemplate(), PointF.Empty())

# 保存文档
newDoc.SaveToFile(outputFile)
newDoc.Close()

通过组合使用 TranslateTransform()ScaleTransform(),你不仅可以调整页面大小,还可以控制内容在新页面中的位置。上面的代码演示了如何将内容居中显示,你也可以根据需要调整为靠左、靠右或其他布局方式。

更改页面方向

除了调整尺寸,你还可以改变页面的方向(纵向或横向),这对于优化宽表格或宽图像的显示效果非常有用:

当文档中包含宽幅内容(如宽表格、流程图或全景图片)时,将页面从纵向改为横向可以更好地利用空间。通过 PdfPageOrientation 枚举可以轻松切换页面方向,同时保持内容的正确比例:

from spire.pdf import *
from spire.pdf.common import *

inputFile = "纵向文档.pdf"
outputFile = "横向文档.pdf"

# 加载原始文档
originalDoc = PdfDocument()
originalDoc.LoadFromFile(inputFile)

with PdfDocument() as newDoc:
    for i in range(originalDoc.Pages.Count):
        page = originalDoc.Pages.get_Item(i)
        
        # 交换宽度和高度实现横向布局
        newWidth = page.Size.Height
        newHeight = page.Size.Width
        
        # 添加横向页面
        margins = PdfMargins(15)
        newPage = newDoc.Pages.Add(
            SizeF(newWidth, newHeight), 
            margins,
            PdfPageRotateAngle.RotateAngle0,
            PdfPageOrientation.Landscape
        )
        
        # 计算缩放比例
        scaleX = newWidth / page.Size.Width
        scaleY = newHeight / page.Size.Height
        scale = min(scaleX, scaleY)
        
        # 应用变换
        newPage.Canvas.ScaleTransform(scale, scale)
        newPage.Canvas.DrawTemplate(page.CreateTemplate(), PointF.Empty())

# 保存文档
newDoc.SaveToFile(outputFile)
newDoc.Close()

将页面从纵向改为横向(或反之)时,关键是交换宽度和高度值。PdfPageOrientation.Landscape 参数明确指定页面方向,虽然在实际渲染中主要通过尺寸来控制。

实战:批量页面尺寸转换工具

结合以上技术,可以构建一个通用的 PDF 页面尺寸批量转换工具:

import os
from spire.pdf import *
from spire.pdf.common import *

class PDFPageResizer:
    def __init__(self):
        pass
    
    def resize_to_standard(self, input_file, output_file, paper_size="A4"):
        """将 PDF 转换为标准纸张尺寸"""
        
        originalDoc = PdfDocument()
        originalDoc.LoadFromFile(input_file)
        
        # 映射纸张尺寸名称到 PdfPageSize 方法
        size_map = {
            "A3": PdfPageSize.A3,
            "A4": PdfPageSize.A4,
            "A5": PdfPageSize.A5,
            "Letter": PdfPageSize.Letter,
            "Legal": PdfPageSize.Legal,
            "Tabloid": PdfPageSize.Tabloid
        }
        
        if paper_size not in size_map:
            raise ValueError(f"不支持的纸张尺寸:{paper_size}")
        
        targetSize = size_map[paper_size]()
        
        with PdfDocument() as newDoc:
            for i in range(originalDoc.Pages.Count):
                page = originalDoc.Pages.get_Item(i)
                
                # 计算缩放比例
                scaleX = targetSize.Width / page.Size.Width
                scaleY = targetSize.Height / page.Size.Height
                scale = min(scaleX, scaleY)
                
                margins = PdfMargins(10)
                newPage = newDoc.Pages.Add(targetSize, margins)
                
                newPage.Canvas.ScaleTransform(scale, scale)
                newPage.Canvas.DrawTemplate(page.CreateTemplate(), PointF.Empty())
        
        newDoc.SaveToFile(output_file)
        print("已将 {0} 转换为 {1} 尺寸".format(
            os.path.basename(input_file), paper_size))
    
    def resize_by_scale(self, input_file, output_file, scale_factor):
        """按比例缩放 PDF 页面"""
        
        if scale_factor <= 0 or scale_factor > 2:
            raise ValueError("缩放比例必须在 0 到 2 之间")
        
        originalDoc = PdfDocument()
        originalDoc.LoadFromFile(input_file)
        
        with PdfDocument() as newDoc:
            for i in range(originalDoc.Pages.Count):
                page = originalDoc.Pages.get_Item(i)
                
                width = page.Size.Width * scale_factor
                height = page.Size.Height * scale_factor
                
                margins = PdfMargins(0.0)
                newPage = newDoc.Pages.Add(SizeF(width, height), margins)
                
                newPage.Canvas.ScaleTransform(scale_factor, scale_factor)
                newPage.Canvas.DrawTemplate(page.CreateTemplate(), PointF.Empty())
        
        newDoc.SaveToFile(output_file)
        print("已将 {0} 缩放 {1} 倍".format(
            os.path.basename(input_file), scale_factor))
    
    def batch_resize(self, input_folder, output_folder, paper_size="A4"):
        """批量转换文件夹中的所有 PDF"""
        
        if not os.path.exists(output_folder):
            os.makedirs(output_folder)
        
        pdf_files = [f for f in os.listdir(input_folder) 
                    if f.lower().endswith('.pdf')]
        
        for filename in pdf_files:
            input_path = os.path.join(input_folder, filename)
            output_path = os.path.join(output_folder, filename)
            
            self.resize_to_standard(input_path, output_path, paper_size)
        
        print("批量处理完成!共处理 {0} 个 PDF 文件".format(len(pdf_files)))

# 使用示例
resizer = PDFPageResizer()

# 单个文件转换为 A4
resizer.resize_to_standard("报告.pdf""A4_报告.pdf", paper_size="A4")

# 按比例缩放
resizer.resize_by_scale("大文档.pdf""缩小版.pdf", scale_factor=0.7)

# 批量转换
resizer.batch_resize("待转换 PDF""已转换 PDF", paper_size="A4")

这个工具类提供了:

  • 转换为多种标准纸张尺寸(A3、A4、A5、Letter 等)
  • 按比例自由缩放
  • 批量处理整个文件夹的 PDF
  • 自动创建输出目录
  • 进度反馈和错误处理

常见问题与解决方案

问题 1:内容被裁剪

确保使用较小的缩放比例以保持内容完整:

scale = min(scaleX, scaleY)  # 而不是 max

问题 2:页面留白过多

调整边距设置或重新计算缩放比例:

margins = PdfMargins(0.0)  # 无边距
# 或者
margins = PdfMargins(5)  # 小边距

问题 3:文字模糊

避免过度放大,如果必须放大,考虑使用较高的 DPI 设置:

# 避免过大的缩放比例
if scale_factor > 1.5:
    print("警告:过度放大可能导致质量下降")

问题 4:页面顺序混乱

确保按正确的索引顺序处理页面:

for i in range(originalDoc.Pages.Count):
    page = originalDoc.Pages.get_Item(i)
    # 依次处理每一页

总结

改变 PDF 页面大小是文档处理和出版工作流中的重要技能。通过本文的介绍,我们学习了:

  1. 使用 ScaleTransform 进行等比例缩放
  2. 转换为标准纸张尺寸(A4、A3、Letter 等)
  3. 自定义页面宽度和高度
  4. 更改页面方向(纵向/横向)
  5. 构建批量页面尺寸转换工具的实战应用

这些技术可以直接应用于打印准备、文档标准化、移动设备优化、印刷出版等实际场景。掌握了基础的页面尺寸调整方法后,还可以进一步探索页面旋转、多页合并、边距调整等高级功能,构建更加完善的 PDF 文档处理系统。