-
Notifications
You must be signed in to change notification settings - Fork 0
/
合并PDF.pyw
147 lines (121 loc) · 4.99 KB
/
合并PDF.pyw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
class DraggableListbox(tk.Listbox):
def __init__(self, master, **kw):
super().__init__(master, **kw)
self.bind('<Button-1>', self.set_current)
self.bind('<B1-Motion>', self.shift_selection)
self.curIndex = None
def set_current(self, event):
self.curIndex = self.nearest(event.y)
def shift_selection(self, event):
i = self.nearest(event.y)
if i < self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i + 1, x)
self.curIndex = i
elif i > self.curIndex:
x = self.get(i)
self.delete(i)
self.insert(i - 1, x)
self.curIndex = i
def convert_images_to_pdf(image_files, output_file, dpi=300, progress_var=None, progress_label=None):
if not image_files:
raise ValueError("没有选择图片文件")
c = canvas.Canvas(output_file)
total_files = len(image_files)
for i, img_path in enumerate(image_files, 1):
with Image.open(img_path) as img:
if img.format == 'WEBP':
img = img.convert('RGB')
width, height = img.size
pdf_w = width * 72.0 / dpi
pdf_h = height * 72.0 / dpi
c.setPageSize((pdf_w, pdf_h))
c.drawImage(ImageReader(img), 0, 0, width=pdf_w, height=pdf_h)
c.showPage()
if progress_var:
progress_var.set(int(i / total_files * 100))
if progress_label:
progress_label.config(text=f"处理中: {i}/{total_files}")
root.update_idletasks()
c.save()
def select_input_folder():
folder = filedialog.askdirectory()
if folder:
input_entry.delete(0, tk.END)
input_entry.insert(0, folder)
update_file_list(folder)
# 设置默认输出文件路径
default_output_file = os.path.join(folder, "output.pdf")
output_entry.delete(0, tk.END)
output_entry.insert(0, default_output_file) # 显示默认输出路径
def update_file_list(folder):
supported_formats = ('.png', '.jpg', '.jpeg', '.webp')
image_files = [f for f in os.listdir(folder) if f.lower().endswith(supported_formats)]
image_files.sort()
file_listbox.delete(0, tk.END)
for file in image_files:
file_listbox.insert(tk.END, file)
def select_output_file():
file = filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF files", "*.pdf")])
if file:
output_entry.delete(0, tk.END)
output_entry.insert(0, file)
def convert():
input_folder = input_entry.get()
output_file = output_entry.get()
dpi = int(dpi_entry.get())
if not input_folder or not output_file:
messagebox.showerror("错误", "请选择输入文件夹和输出文件")
return
try:
progress_var.set(0)
progress_label.config(text="准备中...")
convert_button.config(state=tk.DISABLED)
root.update_idletasks()
image_files = [os.path.join(input_folder, file_listbox.get(i)) for i in range(file_listbox.size())]
convert_images_to_pdf(image_files, output_file, dpi, progress_var, progress_label)
progress_label.config(text="完成!")
messagebox.showinfo("成功", "PDF文件已成功生成")
except Exception as e:
messagebox.showerror("错误", str(e))
finally:
convert_button.config(state=tk.NORMAL)
# 创建主窗口
root = tk.Tk()
root.title("图片到PDF转换器")
# 输入文件夹选择
tk.Label(root, text="图片文件夹:").grid(row=0, column=0, sticky="e", padx=5, pady=5)
input_entry = tk.Entry(root, width=50)
input_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Button(root, text="浏览", command=select_input_folder).grid(row=0, column=2, padx=5, pady=5)
# 文件列表
file_listbox = DraggableListbox(root, selectmode=tk.SINGLE, width=70, height=10)
file_listbox.grid(row=1, column=0, columnspan=3, padx=5, pady=5)
# 输出文件选择
tk.Label(root, text="输出PDF文件:").grid(row=2, column=0, sticky="e", padx=5, pady=5)
output_entry = tk.Entry(root, width=50)
output_entry.grid(row=2, column=1, padx=5, pady=5)
tk.Button(root, text="浏览", command=select_output_file).grid(row=2, column=2, padx=5, pady=5)
# DPI设置
tk.Label(root, text="DPI:").grid(row=3, column=0, sticky="e", padx=5, pady=5)
dpi_entry = tk.Entry(root, width=10)
dpi_entry.insert(0, "300")
dpi_entry.grid(row=3, column=1, sticky="w", padx=5, pady=5)
# 进度条
progress_var = tk.IntVar()
progress_bar = ttk.Progressbar(root, variable=progress_var, maximum=100)
progress_bar.grid(row=4, column=0, columnspan=3, sticky="ew", padx=5, pady=5)
# 进度标签
progress_label = tk.Label(root, text="")
progress_label.grid(row=5, column=0, columnspan=3)
# 转换按钮
convert_button = tk.Button(root, text="转换", command=convert)
convert_button.grid(row=6, column=1, pady=10)
root.mainloop()