在孩子的学习过程中,我们常常会遇到这样的困扰:学校老师发的作业是以 A3 格式的 PDF 文件呈现的,然而家里的打印机却只支持 A4 打印。这时候,要是能有一个简单的方法把 A3 的 PDF 转换为 A4 可打印的格式就好了。别担心,今天我就来分享一下我是如何用 Python 编写一个实用的转换程序,轻松解决这个问题的。

我通过编写 Python 程序,借助几个常见的 Python 库,实现了将 A3 格式的 PDF 文件进行分割和重新组合,最终生成适合 A4 打印机打印的 PDF 文件。整个过程只需要简单的几个步骤,就可以让原本无法直接打印的作业变得可以轻松打印出来。

这个程序主要完成了以下几个关键的任务:

  1. PDF 转图片:把 A3 格式的 PDF 文件逐页转换为图片,并将这些图片保存到一个专门的文件夹中。这样做的好处是方便后续对页面内容进行处理。
  2. 图片分割:将生成的图片从中间左右分割成两张,模拟将 A3 页面拆分成两个 A4 页面的效果。分割后的图片会被保存到另一个新的文件夹中。
  3. 图片合并成 PDF:按照文件名的顺序,将分割后的图片重新合并成一个新的 PDF 文件。这个新的 PDF 文件就是适合 A4 打印机打印的格式了。

下面是具体的代码实现:

#!/usr/bin/python3
# -*- coding: utf-8 -*-import fitz
import time
import os
import sys
import cv2
import numpy as np
from fpdf import FPDF
from PIL import Image# pip install PyMuPDF
# pip install opencv-python
# pip install fpdf
# pip install Pillow
# 将pdf分割为图片,并建立一个images1文件夹保存之 传入要拆解的pdf文件名
def to_image(file_name):dir1 = get_filename_without_ext(file_name) + "_images1"if not os.path.exists(dir1):os.mkdir(dir1)time_start = time.time()doc = fitz.open(file_name)rotate = int(0)zoom_x = 2.0zoom_y = 2.0trans = fitz.Matrix(zoom_x, zoom_y)print("%s开始转换..." % file_name)pg = 0for page in doc:timep_start = time.time()pg += 1pm = page.get_pixmap(matrix=trans, alpha=False)new_full_name = dir1 + "/" + file_name.split(".")[0]filename1 = "{0:s}{1:0>3d}.jpg".format(new_full_name, pg)pm.save(filename1)timep_end = time.time()print('第 ' + str(pg) + ' 页生成图片累计用时:' + str(timep_end - timep_start))time_end = time.time()print('拆解累计用时:' + str(time_end - time_start))# 将images1文件夹中的每个图片,左右分割为两张,并新建images2文件夹以保存文件
def cut_img(file_name):dir1 = get_filename_without_ext(file_name) + "_images1"for img in os.listdir(dir1):#print(img)#image = cv2.imread(dir1 + "/" + img)#解决路径中含有中文的问题image = cv2.imdecode(np.fromfile(dir1 + "/" + img, dtype=np.uint8), cv2.IMREAD_COLOR)if image is None:print("failed to load image")else:x0 = int(image.shape[1]/2)print('x:' + str(x0))dir2 = get_filename_without_ext(file_name) + "_images2"if not os.path.exists(dir2):os.mkdir(dir2)img1 = image[:, 0:x0-100]img2 = image[:, x0-100:]#cv2.imwrite(dir2 + "/" + img[:-4] + '1.jpg', img1)#cv2.imwrite(dir2 + "/" + img[:-4] + '2.jpg', img2)#解决路径中含有中文的问题cv2.imencode('.jpg', img1)[1].tofile(dir2 + "/" + img[:-4] + '1.jpg')cv2.imencode('.jpg', img2)[1].tofile(dir2 + "/" + img[:-4] + '2.jpg')# 将images2文件夹中的图片合并成为一个pdf,按照文件名的顺序 传入输出的pdf文件名
def makePdf(file_name, pdfFileName):dir2 = get_filename_without_ext(file_name) + "_images2"print(dir2)listPages = [dir2 + "/" + imgFileName for imgFileName in os.listdir(dir2)]#print(listPages)cover = Image.open(listPages[0])if cover is None:print('cover is none')else:width, height = cover.sizepdf = FPDF(unit="pt", format = [width, height])for page in listPages:pdf.add_page()pdf.image(page, 0, 0)pdf.output(pdfFileName, "F")# 获取文件名不带后缀
def get_filename_without_ext(filepath):filename_with_extension = os.path.basename(filepath)filename, file_extension = os.path.splitext(filename_with_extension)return filenamedef check(question):option = input(">> " + question + " Yes(Y) // No(N): \n>> ")return option == "Y" or option == "yes" or option == "Yes" or option == "y"def fileObj(filePath):print(">> 载入成功, 当前文件对象路径:" + filePath + "\n")while True:print("### 当前文件对象路径:" + filePath + " ###\n")option = input("请选择要执行的操作: 分割(S), 合并(M), 退出当前对象(Q)\n>>")option = option.upper()if option == "S" and check("是否分割"):to_image(filePath)cut_img(filePath)if option == "M" and check("是否合并"):makePdf(filePath, get_filename_without_ext(filePath) + "_result.pdf")if option == "Q":print(">> 处理完毕\n")breakdef main():print("欢迎使用pdf切割程序\n")while True:option = input("请输入PDF文件路径:\n>>")if option == 'exit' or option == 'quit' or option == 'q':print(">> 退出!\n")breakelif option == '':print(">> 输入为空\n")elif option == 'help' or option == '-h':print(">> 请输入PDF文件路径:\n")else:if not os.path.exists(option):print(">> 路径出错!,请重新输入PDF路径:\n")continuefileObj(option)# 执行
if __name__ == "__main__":if len(sys.argv) < 2:main()else:uipath = sys.argv[1]to_image(uipath)cut_img(uipath)makePdf(uipath, get_filename_without_ext(uipath) + "_result.pdf")

通过运行这个程序,你只需要输入 A3 格式 PDF 文件的路径,程序就会自动完成分割和合并的操作,最终生成一个适合 A4 打印机打印的 PDF 文件。是不是很方便呢?

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/87216.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/87216.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/87216.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Transformer 核心概念转化为夏日生活类比

以下是把 Transformer 核心概念转化为「夏日生活类比」&#xff0c;不用看代码也能秒懂&#xff0c;搭配冰镇西瓜式记忆法&#xff1a; 一、Transformer 夏日冷饮制作流水线 编码器&#xff08;Encoder&#xff09;&#xff1a;相当于「食材处理间」 把输入&#xff08;比如…

【Linux基础知识系列】第二十九篇-基本的网络命令(ping, traceroute, netstat)

在Linux系统中&#xff0c;网络诊断是系统管理员和用户日常工作中不可或缺的一部分。无论是排查网络连接问题、检查网络延迟&#xff0c;还是监控网络状态&#xff0c;掌握一些基本的网络命令至关重要。本文将详细介绍ping、traceroute和netstat这三种常用的网络命令&#xff0…

javaee初阶-多线程

1.什么是线程 1.1 进程 要了解线程我们首先需要了解什么是进程&#xff1f; 运行的程序在操作系统中以进程的方式运行&#xff0c;比如说电脑打开不同的软件&#xff0c;软件就是不同的进程 1.1.1进程的组织方式 通过双向链表 创建进程就是在双向链表上添加PCB 销毁一个进…

N数据分析pandas基础.py

前言&#xff1a;在数据分析领域&#xff0c;Python 的 Pandas 库堪称得力助手。它不仅拥有高效的数据处理能力&#xff0c;还能与 NumPy 完美配合——后者强大的数值计算功能为 Pandas 提供了坚实的技术基础。 目录 Pandas数据分析实战&#xff1a;解锁数据处理的高效之道 数…

卫星通信链路预算之二:带宽和功带平衡

在上一个章节卫星通信链路预算之一&#xff1a;信噪比分配 中&#xff0c;我们介绍了卫星通信链路中最核心的概念&#xff1a;信噪比分配&#xff0c;并给出了卫星通信链路总信噪比的计算公式。 本篇文章&#xff0c;我们将介绍卫星通信链路中的另外一个基本概念&#xff1a;带…

QGIS新手教程5:图层属性查询与表达式筛选技巧

✅ QGIS新手教程5&#xff1a;图层属性查询与表达式筛选技巧 字段筛选、表达式构建器、选择集操作一步到位&#xff01; 目录 ✅ QGIS新手教程5&#xff1a;图层属性查询与表达式筛选技巧&#x1f4c1; 一、示例数据准备&#xff08;继续使用第四篇中的示例&#xff09;&#…

用 el-dialog 做出弹出框是图片

今天项目上用到个功能是点击按钮弹出一个 modal&#xff0c;有遮罩层而且在上面显示图片。 其实就是 el-dialog 的功能&#xff0c;但是 el-dialog 弹出后&#xff0c;有标签关闭按钮还有背景。 解决办法&#xff1a;el-dialog 的 width 设为 0 就可以了。 <template>…

Gartner《Decision Point for Selecting the Right APIMediation Technology》学习心得

一、API 中介技术概述 背景&#xff0c;API 中介技术变得多样化&#xff0c;应用与集成架构师需要借助决策框架&#xff0c;从企业级 API 网关、轻量级网关、入口网关以及服务网格中挑选出适合多粒度服务和 API 的中介技术。 随着无服务器架构与容器管理系统的兴起&#xff0…

快速 SystemC 之旅(一)

快速 SystemC 之旅&#xff08;一&#xff09; 一、前言背景二、实验环境1. 安装步骤2. 验证安装 三、RTL 级硬件描述1. 初看模块2. 二输入与非门 一、前言背景 因项目需求&#xff0c;近期开始开展电子系统级设计&#xff08;ESL&#xff09;进行事务级建模&#xff08;TLM&a…

解决 Golang 下载golang.org/x包失败方案

在 Golang 开发过程中&#xff0c;不少开发者都遇到过这样的困扰&#xff1a;当试图下载golang.org相关包时&#xff0c;会出现访问失败的情况&#xff0c;尤其是golang.org/x系列包&#xff0c;作为众多第三方库依赖的核心组件&#xff0c;其无法正常下载会严重影响项目的开发…

CppCon 2016 学习:BUILDING A MODERN C++ FORGE FOR COMPUTE AND GRAPHICS

你提供的这段文字是关于 设计一个精简但足够的 C 框架来驱动 Vulkan 的目标陈述&#xff0c;属于项目文档或演讲的第一部分 “Goals”。我们可以把它逐项拆解并深入理解&#xff1a; PART (I – I): GOALS&#xff08;目标&#xff09; 总体目标&#xff1a; 构建一个最小但足…

# AI武装大脑:技术管理者如何用人工智能重构认知与决策系统

作为一位经历了15年技术管理实战的老兵&#xff0c;我见过太多项目因为决策失误、认知局限而陷入泥潭。直到我开始系统性地用AI武装大脑&#xff0c;才真正找到了突破技术管理瓶颈的利器。今天&#xff0c;我要分享的不是那些泛泛而谈的AI概念&#xff0c;而是如何用AI真正提升…

【Linux】UDP与TCP协议

目录 UDP协议 1.1通信流程 1.2函数 socket bind sendto recvfrom close 1.3实现udp通信 TCP协议 1.1TCP头部结构 1.2通信流程 三次握手 正式通信 四次挥手 1.3协议特性 面向字节流 可靠传输 序列号和确认号 重传机制 流量控制和拥塞控制 1.4常用函数 s…

gbase8s之MyBatis批量update问题

源代码 <update id"updateDynamicTableData"><foreach collection"mapList" item"map" separator";">UPDATE ${tableName} SET<foreach collection"map" item"value" index"key" separ…

博图SCL中WHILE语句的使用详解及案例

在西门子TIA Portal的SCL&#xff08;结构化控制语言&#xff09;编程中&#xff0c;WHILE循环是处理条件迭代任务的核心工具。它根据布尔表达式动态控制循环执行&#xff0c;适用于不确定循环次数的场景。下面从语法、执行流程、注意事项到实际案例全面解析。 一、WHILE循环基…

简单聊聊JVM中的几种垃圾收集算法

3.4、分代收集算法 分代收集算法&#xff0c;可以看成以上内容的延伸。它的实现思路是根据对象的生命周期的不同&#xff0c;将内存划分为几块&#xff0c;比如把堆空间划分为新生代和老年代&#xff0c;然后根据各块的特点采用最适当的收集算法。 在新生代中&#xff0c;存在…

依赖已导入,已下载,无法使用问题

明明已经导入依赖&#xff0c;却无法使用相关注解 于是&#xff0c;我使用 mvn dependency:tree -Dverbose 来查看是否有依赖冲突 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal on project agileboot…

答题考试系统小程序ThinkPHP+UniApp

ThinkPHPUniapp开发的小程序答题考试系统&#xff0c;支持多种试题类型、多种试题难度、练题、考试、补考模式&#xff0c;提供全部前后台无加密源代码&#xff0c;支持私有化部署. 更新日志 V1.7.1修复一些问题 解决考场成绩列表重复问题&#xff1b; 解决后台材料题选择子…

DHCP服务管理

目录 DHCP协议 DHCP的优势 DHCP的分配方式 应用场景 注意 工作流程 何时更新租约 当客户端重启后 客户端类型 DCHP安装与配置 网络规划&#xff1a; 配置 DHCP 作用域 启动 DHCP 服务 配置路由器 配置路由器网卡 IP 开启 IP 转发&#xff08;确保跨网段通信&…

12.UDP客户端

准备工作 硬件准备&#xff1a;确保你的STM32板子已经正确连接了DP83848网络芯片。 软件设置&#xff1a; 安装好STM32CubeMX用于配置工程。 选择合适的STM32 HAL库版本。 如果可能的话&#xff0c;安装LwIP库支持TCP/IP协议栈。 步骤 1. 使用STM32CubeMX配置项目 打开…