巧用 Python:将 A3 作业 PDF 轻松转为 A4 可打印格式

发布于:2025-06-18 ⋅ 阅读:(14) ⋅ 点赞:(0)

在孩子的学习过程中,我们常常会遇到这样的困扰:学校老师发的作业是以 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.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 文件。是不是很方便呢?

 


网站公告

今日签到

点亮在社区的每一天
去签到