python 图片PDF转换器

图片PDF转换器

图片PDF转换器界面

python 3.7 环境安装

python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ Pillow==9.5.0
python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ reportlab==4.2.5

图片PDF转换器.py

#!/usr/bin/python
# -*- coding: UTF-8 -*-
#import random
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox
import os

# try:
#     import fitz
# except:
#     os.popen("python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ pymupdf==1.18.17")  ##pymupdf==1.18.17 pymupdf==1.20.1
# finally:
#     import fitz
#     print(fitz.__doc__)

try:
    from PIL import Image
except:
    os.popen("python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ Pillow==9.5.0")
finally:
    from PIL import Image

class WinGUI(tk.Tk):
    """窗口类"""
    def __init__(self):
        super().__init__()
        self._win()
        self.frame = ttk.Frame(self)
        if os.name == 'nt':
            self.iconbitmap("C:\Windows\System32\dfrgui.exe")

        self.frame.pack(side=tk.TOP,fill=tk.BOTH,expand=True,padx=15,pady=1)
        self.image_paths = []
        # 添加标签和按钮
        self.tt = ttk.Label(self.frame, text="图片PDF转换器", font="宋体 20 bold").pack(pady=5)

        self.listbox = tk.Listbox(self.frame,height=10)
        self.listbox.pack(fill=tk.X,padx=2,pady=2)

        self.btn_frame = ttk.Frame(self.frame)
        self.btn_frame.pack(fill=tk.BOTH, expand=True, padx=0, pady=10, ipadx=0, ipady=0,anchor=tk.CENTER,)

        self.btn_select = ttk.Button(self.btn_frame, text="选择图片文件", command=self.select_file)
        self.btn_select.pack(side=tk.LEFT,padx=2, pady=2 , fill=tk.BOTH)

        self.btn_del = ttk.Button(self.btn_frame, text="移除选择文件", command=self.delete_item)
        self.btn_del.pack(side=tk.LEFT,padx=2, pady=2, fill=tk.BOTH)

        self.btn_cls = ttk.Button(self.btn_frame, text="清空文件列表", command=self.clear_list)
        self.btn_cls.pack(side=tk.LEFT,padx=2, pady=2, fill=tk.BOTH)

        self.check_var_gui = tk.BooleanVar(value=True)
        self.chbtn_gui = ttk.Checkbutton(self.btn_frame, text="A4页面", variable=self.check_var_gui)
        self.chbtn_gui.pack(side=tk.RIGHT, padx=2, pady=2, fill=tk.BOTH, befor=self.btn_cls)
        # self.chbtn_gui.bind('<ButtonRelease>', checkChange)

        self.btn_save = ttk.Button(self.btn_frame, text="转换PDF和保存", command=self.image_to_pdf)
        self.btn_save.pack(side=tk.RIGHT, padx=2, pady=2, fill=tk.BOTH, befor=self.chbtn_gui)

    def _win(self):
        """设置窗口属性"""
        self.title("图片PDF转换器")
        width = 600
        height = 300
        screenwidth = self.winfo_screenwidth()
        screenheight = self.winfo_screenheight()
        geometry = f"{width}x{height}+{int((screenwidth - width) / 2)}+{int((screenheight - height) / 2)}"
        self.geometry(geometry)
        self.resizable(width=False, height=False)

    def delete_item(self):
        # 获取当前选中项目的索引
        selected_index = self.listbox.curselection()
        # 检查是否有选中的项目
        if selected_index:
            # 删除选中的项目
            self.listbox.delete(selected_index[0])
        else:
            # 如果没有选中的项目,显示消息框
            messagebox.showwarning("删除警告", "请选择一个要删除的项目")

    def clear_list(self):
        # 清空 Listbox
        self.listbox.delete(0, tk.END)

    def select_file(self):
        global images
        images = filedialog.askopenfilenames(initialdir="", title="Select Images")
        for fpath in images:
            self.image_paths.append(fpath)
            ##self.img_var.insert(0, fpath)
            self.listbox.insert(tk.END, fpath)

    def img_to_pdf_resize(self):
        try:
            import os,datetime
            #from PIL import Image
            if self.image_paths:
                tmp_file_name = self.image_paths[0].split('.')[0]
                output_path = filedialog.asksaveasfilename(title='save as file', initialdir='/', filetypes=(('pdf files', '*.pdf'),), initialfile=f"{tmp_file_name}.pdf")
                if len(output_path) >0:
                    new_images = []
                    ###遍历图像路径列表,将每张图像添加到PDF中
                    for image_path in self.image_paths:
                        pil_image = Image.open(image_path)
                        ####获取图像的尺寸(注意:这里使用的是原始尺寸,你可能需要根据需要调整)
                        image_width, image_height = pil_image.size
                        ####设置PDF页面的大小(这里以A4为例,但你可以根据需要调整)
                        page_width = 595.0  # A4宽度,单位为点(1点 = 1/72英寸)
                        page_height = 842.0  # A4高度,单位为点
                        ####计算缩放比例以保持图像的宽高比(这里选择缩放以适应页面宽度)
                        aspect_ratio = image_width / image_height
                        if aspect_ratio > page_width / page_height:
                            ###图像太宽,需要缩放宽度
                            scale = page_width / image_width
                        else:
                            ###图像太高或宽度正好,需要缩放高度
                            scale = page_height / image_height
                        ####计算缩放后的图像尺寸
                        scaled_width = int(image_width * scale)
                        scaled_height = int(image_height * scale)
                        image_d = Image.open(image_path).convert('RGB').resize([scaled_width,scaled_height])
                        new_images.append(image_d)
                    new_images[0].save(output_path, save_all=True, append_images=new_images[1:])
                    # images = [Image.open(image).convert('RGB') for image in sorted(self.image_paths)]
                    # images[0].save(output_path, save_all=True, append_images=images[1:])
                    messagebox.showinfo("Info", f"合并图片为 PDF 文件 {output_path} 成功.")
        except Exception as e:
            messagebox.showinfo("Error", f"合并图片为 PDF 文件时失败! {str(e)}")

    def img_to_pdf(self):
        try:
            #from PIL import Image
            if self.image_paths:
                tmp_file_name = self.image_paths[0].split('.')[0]
                output_path = filedialog.asksaveasfilename(title='save as file', initialdir='/', filetypes=(('pdf files', '*.pdf'),), initialfile=f"{tmp_file_name}.pdf")
                if len(output_path) >0:
                    images = [Image.open(image).convert('RGB') for image in sorted(self.image_paths)]
                    images[0].save(output_path, save_all=True, append_images=images[1:])
                    messagebox.showinfo("Info", f"合并图片为 PDF 文件 {output_path} 成功.")
        except Exception as e:
            messagebox.showinfo("Error", f"合并图片为 PDF 文件时失败! {str(e)}")

    def image_to_pdf_with_a4(self):
        try:
            from reportlab.lib.pagesizes import A4
            from reportlab.pdfgen import canvas
            from reportlab.lib.utils import ImageReader
        except:
            os.popen("python3 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ reportlab==4.2.5")
        finally:
            from reportlab.lib.pagesizes import A4
            from reportlab.pdfgen import canvas
            from reportlab.lib.utils import ImageReader

        try:
            if self.image_paths:
                tmp_file_name = self.image_paths[0].split('.')[0]
                output_path = filedialog.asksaveasfilename(title='save as file', initialdir='/',filetypes=(('pdf files', '*.pdf'),), initialfile=f"{tmp_file_name}.pdf")
                if len(output_path) > 0:
                    print(f"image_to_pdf_with_a4 {output_path}")
                    width, height = A4
                    ###创建一个 Canvas 对象,指定 PDF 文件的路径
                    pdf = canvas.Canvas(output_path, pagesize=A4)
                    page_num = 0
                    num_pages = len(self.image_paths)
                    for image_path in self.image_paths:
                        ####读取图片
                        img = ImageReader(image_path)
                        ####获取图片的宽度和高度(以点为单位,1点 = 1/72英寸)
                        img_width, img_height = img.getSize()
                        ####计算缩放比例,以确保图片适应 A4 纸
                        aspect = img_height / float(img_width)
                        new_height = height
                        new_width = int(height / aspect)
                        if new_width > width:
                            new_width = width
                            new_height = int(width * aspect)
                        # 在 Canvas 上绘制图片,并居中
                        pdf.drawImage(img, (width - new_width) / 2, (height - new_height) / 2, width=new_width,height=new_height)
                        ###如果不是最后一页,则添加新的一页
                        page_num += 1
                        if page_num < num_pages:
                            pdf.showPage()
                    ####保存 PDF 文件
                    pdf.save()
                    messagebox.showinfo("Info", f"合并图片为 PDF 文件 {output_path} 成功.")
        except Exception as e:
            print(e)
            messagebox.showinfo("Error", f"合并图片为 PDF 文件时失败! {str(e)}")

    def image_to_pdf(self):
        print(f"self.check_var_gui {self.check_var_gui.get()}")
        if self.check_var_gui.get() is True:
            print(f"True == {self.check_var_gui.get()}")
            self.image_to_pdf_with_a4()
        else:
            print(f"False == {self.check_var_gui.get()}")
            self.img_to_pdf()

# class Win(WinGUI):
#     def __init__(self, controller):
#         self.ctl = controller
#         super().__init__()
#         self.__event_bind()
#         self.__style_config()
#         self.ctl.init(self)
#
#     def __event_bind(self):
#         pass
#
#     def __style_config(self):
#         pass

if __name__ == "__main__":
    win = WinGUI()
    win.mainloop()

posted @ 2024-12-30 15:15  些许记忆  阅读(23)  评论(0)    收藏  举报