尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
pypdf 页面裁剪与变换完全指南:旋转、缩放、合并与 N-up 排版
pypdf 页面裁剪与变换完全指南旋转、缩放、合并与 N-up 排版【免费下载链接】pypdfA pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files项目地址: https://gitcode.com/GitHub_Trending/py/pypdf本指南以 pypdf 官方文档 docs/user/cropping-and-transforming.md 为核心系统讲解如何在 pypdf 中完成 PDF 页面的旋转、裁剪、缩放与多页合并并深入PageObject、Transformation的源码实现帮助你理解裁剪非删除变换矩阵expand 扩展媒体框等关键机制。读完本文你将能够独立写出旋转页面按比例缩放把一页内容平移/旋转后叠加到另一页一张 A4 排出 16 张名片等实战代码。核心前提裁剪是调整视口而不是删除内容在使用 pypdf 进行任何裁剪操作前必须先建立一条基本认知内容只是不再可见并没有被删除。裁剪Cropping的本质是调整页面的视口viewbox即修改 PDF 页面对象中的/MediaBox、/CropBox等矩形区域被裁掉的内容仍然保存在文件里理论上可以随时通过恢复视口找回。这一点在源码中体现得很直接pypdf 通过_get_rectangle与_set_rectangle两个辅助函数把页面的各种 box 暴露为可读写的属性见 pypdf/_page.py并在 pypdf/generic/_rectangle.py 中提供RectangleObject本质是四个数字组成的数组[left, bottom, right, top]带有left、bottom、right、top、lower_left、upper_right、width、height等便捷属性。因此裁剪在 pypdf 里通常就是一条属性赋值语句。快速上手一个页面同时完成旋转、裁剪与合并官方文档用一个综合示例展示了三种最常用操作的组合——把不同页面以原样、旋转 90°、裁剪一半三种方式写入同一个输出文件from pypdf import PdfReader, PdfWriter reader PdfReader(Seige_of_Vicksburg_Sample_OCR.pdf) writer PdfWriter() # 第 1 页原样加入 writer.add_page(reader.pages[0]) # 第 2 页顺时针旋转 90 度后加入 writer.add_page(reader.pages[1].rotate(90)) # 第 3 页加入后裁剪为原来一半大小 page3 writer.add_page(reader.pages[2]) page3.mediabox.upper_right ( page3.mediabox.right / 2, page3.mediabox.top / 2, ) writer.write(out-all-in-one.pdf)这段代码已经涵盖了本文的全部核心概念rotate(90)做页面旋转mediabox.upper_right赋值做页面裁剪。接下来逐一深入。页面旋转优先使用 rotate 方法最常见的旋转需求是页面方向不对需要按 90 度倍数顺时针转正。pypdf 提供PageObject.rotate(angle)方法实现见 pypdf/_page.pyfrom pypdf import PdfReader, PdfWriter reader PdfReader(example.pdf) writer PdfWriter() writer.add_page(reader.pages[0]) writer.pages[0].rotate(90) writer.write(out-page-rotation.pdf)需要注意两点rotate(angle)要求angle是 90 的倍数否则会抛出ValueError(Rotation angle must be a multiple of 90)——这与 PDF 规范中/Rotate条目只允许 0/90/180/270 的约定一致。它实际上是在原旋转值上累加角度并写回/Rotate字典条目属于元数据级旋转不影响页面内容流。官方文档特别提醒rotate通常优于page.add_transformation(Transformation().rotate())。原因在于rotate只调整/Rotate条目页面仍会保持在 mediabox/cropbox 之内而Transformation对象操作的是页面内容流的坐标往内容流头部插入cm变换矩阵算子见 pypdf/_page.py 的_add_transformation_matrix不会改变 mediabox 或 cropbox因此内容可能旋转出视口。如果确实想把旋转烙进内容与所有页面 box可以调用transfer_rotation_to_content()pypdf/_page.py它会把页面旋转应用到内容流并同步旋转/MediaBox、/CropBox、/BleedBox、/TrimBox、/ArtBox五个矩形——官方建议在页面合并前先执行它以保证各页面坐标系一致。页面合并merge_page 与变换叠加普通合并Plain Merge把另一页内容叠加到当前页最简单的是merge_pagefrom pypdf import PdfReader, PdfWriter reader_base PdfReader(labeled-edges-center-image.pdf) page_base reader_base.pages[0] reader PdfReader(box.pdf) page_box reader.pages[0] writer PdfWriter() page writer.add_page(page_base) page.merge_page(page_box) writer.write(out-plain-merge.pdf)合并的本质是把两页的资源字典字体、XObject 等合并、内容流拼接页面本身的 mediabox/cropbox 不会被改变见 pypdf/_page.py 的merge_page文档与实现。带旋转的合并Merge with Rotation如果要让被合并的页面先做几何变换再叠加使用merge_transformed_page(page2, transformation)from pypdf import PdfReader, PdfWriter, Transformation reader_base PdfReader(labeled-edges-center-image.pdf) page_base reader_base.pages[0] reader PdfReader(box.pdf) page_box reader.pages[0] writer PdfWriter() writer_page writer.add_page(page_base) transformation Transformation().rotate(45) writer_page.merge_transformed_page(page_box, transformation) writer.write(out-merge-with-rotation.pdf)被合并页旋转 45° 后超出目标页视口的部分会被裁掉。此时加上expandTruepypdf 会重新计算媒体框以容纳旋转后的内容transformation Transformation().rotate(45) writer_page.merge_transformed_page(page_box, transformation, expandTrue)还可以配合平移把内容向右挪动op Transformation().rotate(45).translate(tx50) writer_page.merge_transformed_page(page_box, op)Transformation 类与四个便捷合并方法Transformation表示一个二维仿射变换内部保存 6 元组压缩矩阵(a, b, c, d, e, f)对应 PDF 内容流中的cm算子支持rotate(rotation)、scale(sx, sy)、translate(tx, ty)、transform(m)链式组合还提供apply_on(pt)用于把变换作用到某个坐标点见 pypdf/_page.py。基于它pypdf 还封装了三个更专用的合并方法实现均在 pypdf/_page.pymerge_scaled_page(page2, scale, overTrue, expandFalse)按比例缩放后合并merge_rotated_page(page2, rotation, overTrue, expandFalse)按角度旋转后合并merge_translated_page(page2, tx, ty, overTrue, expandFalse)平移后合并。三者内部都转调merge_transformed_page。此外merge_page与各合并方法都接受over参数True默认把被合并页内容绘制在上层False则绘制在下层。expand 的底层原理expandTrue时pypdf 调用_expand_mediaboxpypdf/_page.py取被合并页媒体框的四个角点用变换矩阵逐点计算新坐标再与当前页媒体框取并集得到能够容纳两页内容的最小矩形并写回mediabox。add_transformation(ctm, expandTrue)也做了类似计算pypdf/_page.py。该行为有测试佐证tests/test_page.py中的test_mediabox_expansion_after_rotation对 175°、45°、-80° 等非直角旋转验证了展开后媒体框的宽高tests/test_page.pytest_transformation_equivalence则验证了add_transformation merge_page与merge_transformed_page两条路径的等价性tests/test_page.py。缩放内容缩放与页面缩放要分清官方文档强调在 pypdf 中内容contents和页面page/canvas可以一起缩放也可以分别缩放。实际使用中通常需要两者结合。页面与内容一起缩放from pypdf import PdfReader, PdfWriter reader PdfReader(side-by-side-subfig.pdf) page reader.pages[0] writer PdfWriter() writer_page writer.add_page(page) writer_page.scale_by(0.5) # 整体缩小一半 writer.write(out-scale-all.pdf)scale_by(factor)等价于scale(factor, factor)scale(sx, sy)的实现pypdf/_page.py做了三件事先对内容流施加变换矩阵再按比例缩放bleedbox、trimbox、artbox、cropbox、mediabox五个页面 box最后同步缩放页面上所有注释annotations的/Rect。也就是说一起缩放 内容变换 全部视口同步变换。若想缩放到指定尺寸可用scale_to(width, height)pypdf/_page.py它根据当前媒体框宽度计算sx、sy后调用scale。仅缩放内容内容缩放围绕坐标系原点进行PDF 坐标原点通常在左下角from pypdf import PdfReader, PdfWriter, Transformation reader PdfReader(side-by-side-subfig.pdf) page reader.pages[0] writer PdfWriter() writer_page writer.add_page(page) op Transformation().scale(sx0.7, sy0.7) writer_page.add_transformation(op) writer.write(out-scale-content.pdf)Transformation.scale(sx, sy)要求至少指定一个参数另一个缺省时取相同的值pypdf/_page.py。add_transformation只往内容流头部插入cm矩阵不改动任何页面 box所以内容缩放后可能超出页面边界——如果希望页面也随之扩展同样可以传expandTrue。仅缩放页面只缩放页面尺寸画布而不动内容直接对媒体框做矩形缩放即可page.mediabox page.mediabox.scale(sx0.7, sy0.7)RectangleObject.scale(sx, sy)pypdf/generic/_rectangle.py返回缩放后的新矩形。想要更精细的控制可以直接用RectangleObject分别设置各个 boxfrom pypdf.generic import RectangleObject mb page.mediabox page.mediabox RectangleObject((mb.left, mb.bottom, mb.right, mb.top)) page.cropbox RectangleObject((mb.left, mb.bottom, mb.right, mb.top)) page.trimbox RectangleObject((mb.left, mb.bottom, mb.right, mb.top)) page.bleedbox RectangleObject((mb.left, mb.bottom, mb.right, mb.top)) page.artbox RectangleObject((mb.left, mb.bottom, mb.right, mb.top))五个 box 的含义MediaBox是页面物理尺寸CropBox是显示/打印时的可见区域默认等于 MediaBoxTrimBox/BleedBox/ArtBox面向印刷工序。由于它们是矩形属性而非内容变换任意赋值都不会影响页面内容流。页面合并时使用哪个 boxpage_merge_box 配置一个值得注意的兼容性细节pypdf 3.4.0在合并页面时使用被合并页的trimbox作为裁剪边界而pypdf 3.4.0改为使用cropbox。这一行为由配置项page_merge_box控制默认值为cropbox见 pypdf/_configuration.py并在合并流程中通过getattr(page2, configuration.page_merge_box)读取pypdf/_page.py。如果你有充分理由恢复旧行为可通过overwrite_configuration全局覆盖当前执行上下文from pypdf import overwrite_configuration overwrite_configuration(page_merge_boxtrimbox)overwrite_configuration基于ContextVar实现上下文级配置覆盖pypdf/_configuration.py同模块还提供apply_configuration上下文管理器用于临时覆盖、结束后自动还原。实战用变换把同一页面复制 16 次N-up 排版官方文档给出了一个非常典型的 N-up 应用场景把一张 A8 名片复制 16 次排到一张 A4 页面上用于打印裁剪。pypdf 提供了现成的纸张尺寸常量PaperSize.A4宽 595pt × 高 842pt与PaperSize.A8147 × 210定义见 pypdf/papersizes.py。from pypdf import PaperSize, PdfReader, PdfWriter, Transformation # 读取源文件 reader PdfReader(nup-source.pdf) sourcepage reader.pages[0] # 创建目标文件并添加一张横向 A4 空白页 writer PdfWriter() destpage writer.add_blank_page(widthPaperSize.A4.height, heightPaperSize.A4.width) # 把源页面复制 16 次到目标页面 for x in range(4): for y in range(4): # 平移页面 transformation Transformation().translate( x * PaperSize.A8.height, y * PaperSize.A8.width, ) # 合并平移后的页面 destpage.merge_transformed_page(sourcepage, transformation) # 写入文件 writer.write(out-nup-dest1.pdf)要点解析add_blank_page(width..., height...)创建空白目标页传入PaperSize.A4.height作为宽度、PaperSize.A4.width作为高度即得到一张横向 A4内层循环用Transformation().translate(tx, ty)按 A8 的宽高计算每个名片的落点再通过merge_transformed_page逐一叠加变换矩阵链式累加因此每次合并的源页面内容互不影响。官方文档也坦言这种写法需要手动把源页媒体框扩展成整张 A8属于临时的 hack要生成带间距的精美排版还需在此基础上插入边距计算文档将其留作读者练习。常见问题为什么合并后内容被裁掉了官方文档在最后专门提醒当merge_page与变换组合使用时很容易得到内容被裁剪的 PDF。原因正如前文所述merge_page系列方法默认不会改动目标页的媒体框而旋转、平移、缩放可能让被合并内容超出视口。解决思路很明确对merge_page、merge_transformed_page、merge_scaled_page、merge_rotated_page、merge_translated_page以及add_transformation传入expandTrue让 pypdf 基于变换矩阵重新计算并扩展媒体框对应_expand_mediabox逻辑若旋转角度不是 90° 的倍数务必使用expandTrue否则旋转出的倾斜内容几乎必然溢出视口相关行为可参考 tests/test_page.py 中的非直角旋转测试在页面合并前可先对带旋转的页面调用transfer_rotation_to_content()统一坐标系降低变换叠加时的意外。至此你已经掌握了 pypdf 裁剪与变换的完整工具箱用rotate修正页面方向、用mediabox裁剪视口、用Transformation链式构造旋转/缩放/平移、用merge_*系列方法叠加页面并用expand与page_merge_box配置解决边界与兼容性问题。更多页面 API 可继续查阅 pypdf/_page.py 与 docs/user 下的其他指南。【免费下载链接】pypdfA pure-python PDF library capable of splitting, merging, cropping, and transforming the pages of PDF files项目地址: https://gitcode.com/GitHub_Trending/py/pypdf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

ODS Lemonade SDK适配:AMD加速推理路径全解析

ODS Lemonade SDK适配:AMD加速推理路径全解析

ODS Lemonade SDK适配:AMD加速推理路径全解析 【免费下载链接】ODS Turn your PC, Mac, or Linux box into an AI server. LLM inference, chat UI, voice, agents, workflows, RAG, and image generation. 项目地址: https://gitcode.com/GitHub_Trending/dr/ODS…

📅 2026/9/16 19:14:10
Jetson Orin高可靠AI开发环境部署指南

Jetson Orin高可靠AI开发环境部署指南

1. 项目概述:这不是一次普通系统安装,而是为Jetson Orin构建高可靠性边缘AI开发基座“orin-开发环境部署2”这个标题看似平淡,实则藏着一个硬核事实:它不是教你怎么点几下鼠标装个Ubuntu,而是在为NVIDIA Jetson Orin系…

📅 2026/9/16 19:14:10
Stream 视频边缘网络(SFU)架构解析:Vision-Agents 电话 RAG 示例中的 video.md 知识库文档

Stream 视频边缘网络(SFU)架构解析:Vision-Agents 电话 RAG 示例中的 video.md 知识库文档

Stream 视频边缘网络(SFU)架构解析:Vision-Agents 电话 RAG 示例中的 video.md 知识库文档 【免费下载链接】Vision-Agents Open Vision Agents by Stream. Build voice and vision agents quickly with any model or video provider. Uses S…

📅 2026/9/16 19:14:10
MORE NEWS

更多资讯

📰

STM32串口控制步进电机速度与角度:脉冲换算与协议解析实战

简介:基于STM32的步进电机串口控制工程包,面向嵌入式初学者、电子竞赛选手及需要开发精确运动控制的STM32开发者,主要解决上位机通过串口发送指令后对步进电机速度与角度进行精细调节的问题。压缩包共216个文件,约3.41MB&#xff…

📰

React Native运行环境区分:模拟器与真机调试全指南

2. 为什么你的RN项目总卡在“环境区分”这一步先说个现象。我做React Native开发这几年,最常被问到的问题不是“组件怎么写”,而是“我明明照着官网装的,为什么npx react-native run-android之后就是跑不起来”。这个问题十有八九出在环境上&…

📰

STM32与ESP8266的AT指令通信:从UART接线到断线重连的完整指南

简介:基于STM32与ESP8266的AT指令实现工程,面向嵌入式开发与物联网学习者,演示如何通过串口向ESP8266发送AT指令完成无线网络连接、TCP数据传输等常用操作,适合正在入门STM32与Wi-Fi模块联合开发的读者。压缩包内含248个文件&…

📰

iOS Universal Links校验不通过?从AASA配置到排查的完整指南

先把结论放前面:如果你正在被 “universal link 校验不通过” 这个报错反复折腾,那这篇内容值得你读完。Universal Links(通用链接)在 iOS 8 时代之前靠 URL Scheme 也能做唤起,但体验和安全性都不是一回事。iOS 9 之后…

📰

SpiderMonkey 的 iongraph:用 GraphViz 可视化 IonMonkey 优化图的完整指南

SpiderMonkey 的 iongraph:用 GraphViz 可视化 IonMonkey 优化图的完整指南 【免费下载链接】mongo The MongoDB Database 项目地址: https://gitcode.com/GitHub_Trending/mo/mongo 本文基于 iongraph 官方文档 撰写,并结合 SpiderMonkey 源码中 …

📰

IEC 101规约C语言实现:帧结构解析与南瑞RTU调试实战

简介:面向电力系统远动通信、RTU设备调试及IEC 60870-5-101规约初学者,这份来自南瑞工程现场的RTU101小工具压缩包,将规约文档与可运行源码整合在一起,帮助快速绕开协议细节的弯路。包内共有2个文件,1个cpp源码文件用于…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬