在孩子的学习过程中,我们常常会遇到这样的困扰:学校老师发的作业是以 A3 格式的 PDF 文件呈现的,然而家里的打印机却只支持 A4 打印。这时候,要是能有一个简单的方法把 A3 的 PDF 转换为 A4 可打印的格式就好了。别担心,今天我就来分享一下我是如何用 Python 编写一个实用的转换程序,轻松解决这个问题的。
我通过编写 Python 程序,借助几个常见的 Python 库,实现了将 A3 格式的 PDF 文件进行分割和重新组合,最终生成适合 A4 打印机打印的 PDF 文件。整个过程只需要简单的几个步骤,就可以让原本无法直接打印的作业变得可以轻松打印出来。
这个程序主要完成了以下几个关键的任务:
- PDF 转图片:把 A3 格式的 PDF 文件逐页转换为图片,并将这些图片保存到一个专门的文件夹中。这样做的好处是方便后续对页面内容进行处理。
- 图片分割:将生成的图片从中间左右分割成两张,模拟将 A3 页面拆分成两个 A4 页面的效果。分割后的图片会被保存到另一个新的文件夹中。
- 图片合并成 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.0
zoom_y = 2.0
trans = fitz.Matrix(zoom_x, zoom_y)
print("%s开始转换..." % file_name)
pg = 0
for page in doc:
timep_start = time.time()
pg += 1
pm = 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.size
pdf = 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 filename
def 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")
break
def main():
print("欢迎使用pdf切割程序\n")
while True:
option = input("请输入PDF文件路径:\n>>")
if option == 'exit' or option == 'quit' or option == 'q':
print(">> 退出!\n")
break
elif option == '':
print(">> 输入为空\n")
elif option == 'help' or option == '-h':
print(">> 请输入PDF文件路径:\n")
else:
if not os.path.exists(option):
print(">> 路径出错!,请重新输入PDF路径:\n")
continue
fileObj(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 文件。是不是很方便呢?