python小工具—图片拼接PDF

诉求

在看漫画时,发现图片格式的漫画,调整大小、每页查看,看起来比较麻烦,于是想到做一个图片拼接PDF的小工具。

效果展示

图片合并PDF

文件夹下所有图片→PDF

通过PIL库处理图片的读取、通道转换RGB,最后拼接文件路径进行保存输出。

    def combine_imgs_pdf(self, file_path):
        files = os.listdir(file_path)
        png_files = []
        sources = []
        for file in files:
            if 'png' in file or 'jpg' in file:
                png_files.append(file_path + '\\' + file)
        png_files.sort()
        output = Image.open(png_files[0])
        png_files.pop(0)
        for file in png_files:
            png_file = Image.open(file)
            if png_file.mode == "RGB":
                png_file = png_file.convert("RGB")
            sources.append(png_file)
        pdfName = os.path.basename(file_path) + '.pdf'
        output.save(file_path + '\\' + pdfName, "pdf", save_all=True, append_images=sources)
        print("已输出" + pdfName + "在原文件夹下")

递归寻找所有文件夹

判断是否为文件夹,不断地存储文件夹的路径以备调用

    def generate_folder(self, file_path):
        for folder in os.listdir(file_path):
            path = file_path + '/' + folder
            if os.path.isdir(path):
                self.folder_list.append(path)
                self.generate_folder(path)

完整代码

结合tkinter实现UI界面操作,可满足选取文件夹、拼接文件夹下所有图片为PDF、消息面板、清除面板信息的功能。

import os
import threading
import tkinter as tk
from tkinter import *
from tkinter.filedialog import askdirectory, askopenfilename

from PIL import Image, ImageFile

# 将图片失效信息抛掉
ImageFile.LOAD_TRUNCATED_IMAGES = True


def thread_it(func, *args):
    """将函数打包进线程"""
    # 创建
    t = threading.Thread(target=func, args=args)
    # 守护 !!!
    t.setDaemon(True)
    # 启动
    t.start()
    # 阻塞--卡死界面!
    # t.join()


class GUI:

    def __init__(self):
        self.root = tk.Tk()
        self.root.title("DDPl图片拼接PDF")
        self.root.configure(bg='#2c3038')
        self.root.option_add('*Font', '楷体')
        # self.root.geometry("500x200+1100+150")
        # 程序运行时在屏幕中间打开
        sw = self.root.winfo_screenwidth()
        sh = self.root.winfo_screenheight()
        ww = 1055
        wh = 580
        x = (sw - ww) / 2
        y = (sh - wh) / 3
        self.root.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
        self.root.resizable(False, False)
        self.root.update()
        self.root.wm_attributes('-topmost', 1)
        self.interface()
        self.file_path = "file_path"
        self.folder_list = []

    def interface(self):
        self.w1 = tk.Entry(self.root, textvariable='请输入目标路径', bg='#25272c', fg='#b2b2b2')
        self.w1.grid(row=0, column=0, columnspan=2, ipadx=210, ipady=8, padx=10, pady=10)
        self.Button1 = tk.Button(self.root, text="选择文件夹", command=lambda: thread_it(self.event_选择目标文件夹), width=10,
                                 bg='#4780ac', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button1.grid(row=0, column=2, ipadx=20, ipady=10, padx=5, pady=10)
        self.Button2 = tk.Button(self.root, text="拼接PDF", command=lambda: thread_it(self.event_图片合并PDF), width=10,
                                 bg='#4a8e53', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button2.grid(row=0, column=4, ipadx=20, ipady=10, padx=5, pady=10)
        self.Button3 = tk.Button(self.root, text="清空输出信息", command=lambda: thread_it(self.event_清空输出信息), width=10,
                                 bg='#2c3038', fg='#d9f5ff', activebackground='#4d535f', activeforeground='#fdfdfd')
        self.Button3.grid(row=0, column=5, ipadx=20, ipady=10, padx=5, pady=10)
        self.text = tk.Text(self.root, bg='#25272c', fg='#777c8a')
        self.text.grid(row=1, column=0, columnspan=6, ipadx=195, ipady=50, padx=10, pady=10)
        # 新建滚动条
        self.scroll = tk.Scrollbar()
        # 两个控件关联
        self.scroll.config(command=self.text.yview)
        self.text.config(yscrollcommand=self.scroll.set)

    def event_选择目标文件夹(self):
        self.file_path = askdirectory()  # 使用askdirectory()方法返回文件夹的路径
        if self.file_path == "":
            self.w1.get()  # 当打开文件路径选择框后点击"取消" 输入框会清空路径,所以使用get()方法再获取一次路径
        else:
            path_ = self.file_path.replace("/", "\\")  # 实际在代码中执行的路径为“\“ 所以替换一下
            self.w1.delete(0, END)
            self.w1.insert(0, path_)

    def event_图片合并PDF(self):
        self.generate_folder(self.file_path)
        self.w1.delete(0, END)
        self.w1.insert(0, self.folder_list)
        if len(self.folder_list) == 0:
            self.combine_imgs_pdf(self.file_path)
        else:
            for folder in self.folder_list:
                self.combine_imgs_pdf(folder)

    def generate_folder(self, file_path):
        for folder in os.listdir(file_path):
            path = file_path + '/' + folder
            if os.path.isdir(path):
                self.folder_list.append(path)
                self.text.insert(tk.INSERT, "已找到文件夹" + path + '\n')
                self.text.see(END)
                self.generate_folder(path)

    # 合并文件夹下所有图片为PDF
    def combine_imgs_pdf(self, file_path):
        files = os.listdir(file_path)
        png_files = []
        sources = []
        for file in files:
            if 'png' in file or 'jpg' in file:
                png_files.append(file_path + '\\' + file)
        png_files.sort()
        output = Image.open(png_files[0])
        png_files.pop(0)
        for file in png_files:
            png_file = Image.open(file)
            if png_file.mode == "RGB":
                png_file = png_file.convert("RGB")
            sources.append(png_file)
            self.text.insert(tk.INSERT, "正在拼接" + file + '\n')
            self.text.see(END)
        pdfName = os.path.basename(file_path) + '.pdf'
        output.save(file_path + '\\' + pdfName, "pdf", save_all=True, append_images=sources)
        self.text.insert(tk.INSERT, "已输出" + pdfName + "在原文件夹下" + '\n')
        self.text.see(END)
        print("已输出" + pdfName + "在原文件夹下")

    def event_清空输出信息(self):
        try:
            self.text.delete('1.0', END)
        except Exception as e:
            print(e)
            pass


if __name__ == "__main__":
    a = GUI()
    a.root.mainloop()
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值