|
|
|
|
@ -1,5 +1,6 @@
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import platform
|
|
|
|
|
from fpdf import FPDF
|
|
|
|
|
|
|
|
|
|
from PIL import Image
|
|
|
|
|
@ -9,6 +10,11 @@ from tkinter.filedialog import askdirectory, askopenfiles
|
|
|
|
|
from pypdf import PdfWriter, PdfReader, Transformation
|
|
|
|
|
import math
|
|
|
|
|
import random
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_os():
|
|
|
|
|
return platform.system()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_output(path):
|
|
|
|
|
@ -19,22 +25,22 @@ def check_output(path):
|
|
|
|
|
os.mkdir(dir_name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def img_to_pdf(img_path, out_path='', x=0, y=0, w=100, h=100):
|
|
|
|
|
''' 图片转PDF'''
|
|
|
|
|
if out_path == '':
|
|
|
|
|
def img_to_pdf(img_path, out_path="", x=0, y=0, w=100, h=100):
|
|
|
|
|
"""图片转PDF"""
|
|
|
|
|
if out_path == "":
|
|
|
|
|
dir_name = os.path.dirname(img_path)
|
|
|
|
|
basename = os.path.basename(img_path)
|
|
|
|
|
name, _ = os.path.splitext(basename)
|
|
|
|
|
out_path = os.path.join(dir_name, name+'.pdf')
|
|
|
|
|
out_path = os.path.join(dir_name, name + ".pdf")
|
|
|
|
|
pdf = FPDF()
|
|
|
|
|
pdf.add_page()
|
|
|
|
|
pdf.image(img_path, x=x, y=y, w=w, h=h)
|
|
|
|
|
pdf.output(out_path, 'F')
|
|
|
|
|
pdf.output(out_path, "F")
|
|
|
|
|
return out_path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_image_watermark(input_path, watermark_path, output_path):
|
|
|
|
|
''' 图片添加印章 '''
|
|
|
|
|
"""图片添加印章"""
|
|
|
|
|
# 打开原始图片和要添加的水印图片
|
|
|
|
|
original_img = Image.open(input_path).convert("RGBA")
|
|
|
|
|
watermark_img = Image.open(watermark_path).convert("RGBA")
|
|
|
|
|
@ -47,20 +53,27 @@ def add_image_watermark(input_path, watermark_path, output_path):
|
|
|
|
|
watermark_img = watermark_img.rotate(random.uniform(-180, 180))
|
|
|
|
|
|
|
|
|
|
# 合并原始图片和水印图片,并将结果转换为RGB模式
|
|
|
|
|
original_img.paste(watermark_img, (math.ceil(original_width - original_width/2.6),
|
|
|
|
|
math.ceil(original_height-original_height/2.6)), watermark_img)
|
|
|
|
|
original_img.paste(
|
|
|
|
|
watermark_img,
|
|
|
|
|
(
|
|
|
|
|
math.ceil(original_width - original_width / 2.6),
|
|
|
|
|
math.ceil(original_height - original_height / 2.6),
|
|
|
|
|
),
|
|
|
|
|
watermark_img,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# 保存水印后的图片
|
|
|
|
|
original_img.save(output_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def add_pdf_watermark(intput_file, watermark_path, output_path):
|
|
|
|
|
''' PDF添加印章 '''
|
|
|
|
|
"""PDF添加印章"""
|
|
|
|
|
stamp = PdfReader(watermark_path).pages[0]
|
|
|
|
|
writer = PdfWriter(clone_from=intput_file)
|
|
|
|
|
for page in writer.pages:
|
|
|
|
|
page.merge_transformed_page(
|
|
|
|
|
stamp, Transformation().translate(980, 60).scale(0.37))
|
|
|
|
|
stamp, Transformation().translate(980, 60).scale(0.37)
|
|
|
|
|
)
|
|
|
|
|
writer.write(output_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -76,8 +89,7 @@ class CustomMessageBox(Toplevel):
|
|
|
|
|
# 设置了宽和高
|
|
|
|
|
self.width = width
|
|
|
|
|
self.height = height
|
|
|
|
|
self.geometry(
|
|
|
|
|
f'{width}x{height}+{master.winfo_x()}+{master.winfo_y()}')
|
|
|
|
|
self.geometry(f"{width}x{height}+{master.winfo_x()}+{master.winfo_y()}")
|
|
|
|
|
|
|
|
|
|
self.grab_set() # 使得对话框不会在点击窗口之外的地方时关闭
|
|
|
|
|
self.wait_window(self) # 等待对话框关闭
|
|
|
|
|
@ -86,21 +98,23 @@ class CustomMessageBox(Toplevel):
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
multi_files = [] # 多选的文件
|
|
|
|
|
dir_files = [] # 文件夹中的文件
|
|
|
|
|
water_path = '' # 印章路径
|
|
|
|
|
tmp_water = '' # 当为图片时,删除临时生成的PDF印章
|
|
|
|
|
last_stamped = '' # 最后一个添加印章后的文件
|
|
|
|
|
water_path = "" # 印章路径
|
|
|
|
|
tmp_water = "" # 当为图片时,删除临时生成的PDF印章
|
|
|
|
|
last_stamped = "" # 最后一个添加印章后的文件
|
|
|
|
|
|
|
|
|
|
print(print(get_os()))
|
|
|
|
|
|
|
|
|
|
def reset():
|
|
|
|
|
global multi_files, dir_files, water_path, tmp_water
|
|
|
|
|
multi_files = []
|
|
|
|
|
dir_files = []
|
|
|
|
|
water_path = ''
|
|
|
|
|
tmp_water = ''
|
|
|
|
|
lable_dir.config(text='')
|
|
|
|
|
lable_files.config(text='')
|
|
|
|
|
lable_stamp.config(text='')
|
|
|
|
|
label_create.config(text='')
|
|
|
|
|
button_create.config(state='disabled')
|
|
|
|
|
water_path = ""
|
|
|
|
|
tmp_water = ""
|
|
|
|
|
lable_dir.config(text="")
|
|
|
|
|
lable_files.config(text="")
|
|
|
|
|
lable_stamp.config(text="")
|
|
|
|
|
label_create.config(text="")
|
|
|
|
|
button_create.config(state="disabled")
|
|
|
|
|
button_opendir.place_forget()
|
|
|
|
|
button_openfile.place_forget()
|
|
|
|
|
|
|
|
|
|
@ -111,17 +125,19 @@ if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
def check_status():
|
|
|
|
|
# 如果文件和水印都选择便启用水印生成按钮,否则禁用
|
|
|
|
|
if ((lable_files.cget('text') != '' or lable_dir.cget('text') != '') and lable_stamp.cget('text') != ''):
|
|
|
|
|
button_create.config(state='normal')
|
|
|
|
|
if (
|
|
|
|
|
lable_files.cget("text") != "" or lable_dir.cget("text") != ""
|
|
|
|
|
) and lable_stamp.cget("text") != "":
|
|
|
|
|
button_create.config(state="normal")
|
|
|
|
|
else:
|
|
|
|
|
button_create.config(state='disabled')
|
|
|
|
|
button_create.config(state="disabled")
|
|
|
|
|
|
|
|
|
|
def select_files(extensions=['pdf', 'png', 'jpeg', 'jpg']):
|
|
|
|
|
def select_files(extensions=["pdf", "png", "jpeg", "jpg"]):
|
|
|
|
|
Tk().withdraw()
|
|
|
|
|
files = askopenfiles()
|
|
|
|
|
# 检测文件类型
|
|
|
|
|
for item in files:
|
|
|
|
|
file_extension = item.name.split('.')[-1].lower()
|
|
|
|
|
file_extension = item.name.split(".")[-1].lower()
|
|
|
|
|
if file_extension not in extensions:
|
|
|
|
|
CustomMessageBox(root, "无效的文件类型。")
|
|
|
|
|
select_files()
|
|
|
|
|
@ -129,9 +145,9 @@ if __name__ == "__main__":
|
|
|
|
|
paths = [(item.name) for item in files]
|
|
|
|
|
global multi_files
|
|
|
|
|
multi_files = paths
|
|
|
|
|
str = ','.join(paths)
|
|
|
|
|
str = ",".join(paths)
|
|
|
|
|
if len(str) >= 50:
|
|
|
|
|
str = str[:50] + '...'
|
|
|
|
|
str = str[:50] + "..."
|
|
|
|
|
lable_files.config(text=str)
|
|
|
|
|
check_status()
|
|
|
|
|
|
|
|
|
|
@ -143,21 +159,21 @@ if __name__ == "__main__":
|
|
|
|
|
global dir_files
|
|
|
|
|
dir_files = items
|
|
|
|
|
if len(folder_path) >= 50:
|
|
|
|
|
folder_path = str[:50] + '...'
|
|
|
|
|
folder_path = str[:50] + "..."
|
|
|
|
|
lable_dir.config(text=folder_path)
|
|
|
|
|
check_status()
|
|
|
|
|
|
|
|
|
|
def select_file(label, extensions=['png', 'jpeg', 'jpg']):
|
|
|
|
|
def select_file(label, extensions=["png", "jpeg", "jpg"]):
|
|
|
|
|
Tk().withdraw()
|
|
|
|
|
file_path = filedialog.askopenfilename()
|
|
|
|
|
if file_path:
|
|
|
|
|
file_extension = file_path.split('.')[-1].lower()
|
|
|
|
|
file_extension = file_path.split(".")[-1].lower()
|
|
|
|
|
if file_extension in extensions:
|
|
|
|
|
# 隐藏操作按钮
|
|
|
|
|
button_opendir.place_forget()
|
|
|
|
|
button_openfile.place_forget()
|
|
|
|
|
if len(file_path) >= 50:
|
|
|
|
|
file_path = str[:50] + '...'
|
|
|
|
|
file_path = str[:50] + "..."
|
|
|
|
|
label.config(text=file_path)
|
|
|
|
|
# 检查水印生成按键可用状态
|
|
|
|
|
check_status()
|
|
|
|
|
@ -171,7 +187,12 @@ if __name__ == "__main__":
|
|
|
|
|
for root, dirs, files in os.walk(dir_path):
|
|
|
|
|
for file in files:
|
|
|
|
|
# 检查文件是否是PDF或图片
|
|
|
|
|
if file.endswith('.pdf') or file.endswith('.png') or file.endswith('.jpg') or file.endswith('.jpeg'):
|
|
|
|
|
if (
|
|
|
|
|
file.endswith(".pdf")
|
|
|
|
|
or file.endswith(".png")
|
|
|
|
|
or file.endswith(".jpg")
|
|
|
|
|
or file.endswith(".jpeg")
|
|
|
|
|
):
|
|
|
|
|
# 如果是,则将其完整路径添加到列表中
|
|
|
|
|
file_list.append(os.path.join(root, file))
|
|
|
|
|
return file_list
|
|
|
|
|
@ -181,31 +202,30 @@ if __name__ == "__main__":
|
|
|
|
|
name, suffix = os.path.splitext(baseaname)
|
|
|
|
|
dir_path = os.path.dirname(file_path)
|
|
|
|
|
# # 判断目标文件是图片还是PDF
|
|
|
|
|
if suffix.lower() == '.pdf':
|
|
|
|
|
if suffix.lower() == ".pdf":
|
|
|
|
|
global tmp_water
|
|
|
|
|
# 如果水印是图片,先转成PDF
|
|
|
|
|
if tmp_water == '':
|
|
|
|
|
if water_path.split('.')[-1].lower() != 'pdf':
|
|
|
|
|
if tmp_water == "":
|
|
|
|
|
if water_path.split(".")[-1].lower() != "pdf":
|
|
|
|
|
tmp_water = img_to_pdf(water_path)
|
|
|
|
|
out_path = os.path.join(
|
|
|
|
|
dir_path, 'output', name + '_watered' + suffix)
|
|
|
|
|
out_path = os.path.join(dir_path, "output", name + "_watered" + suffix)
|
|
|
|
|
check_output(out_path)
|
|
|
|
|
add_pdf_watermark(file_path, tmp_water, out_path)
|
|
|
|
|
else:
|
|
|
|
|
out_path = os.path.join(
|
|
|
|
|
dir_path, 'output', name + '_watered' + '.png')
|
|
|
|
|
out_path = os.path.join(dir_path, "output", name + "_watered" + ".png")
|
|
|
|
|
check_output(out_path)
|
|
|
|
|
add_image_watermark(file_path, water_path, out_path)
|
|
|
|
|
# 显示操作按钮
|
|
|
|
|
global last_stamped
|
|
|
|
|
last_stamped = out_path
|
|
|
|
|
label_create.config(text='生成成功:')
|
|
|
|
|
label_create.place(x=120, y=4*padding_y,
|
|
|
|
|
width=80, height=lable_height)
|
|
|
|
|
button_openfile.place(x=200, y=4*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
button_opendir.place(x=280, y=4*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
label_create.config(text="生成成功:")
|
|
|
|
|
label_create.place(x=120, y=4 * padding_y, width=80, height=lable_height)
|
|
|
|
|
button_openfile.place(
|
|
|
|
|
x=200, y=4 * padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
button_opendir.place(
|
|
|
|
|
x=280, y=4 * padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def multi_watermask():
|
|
|
|
|
global multi_files, dir_files, tmp_water
|
|
|
|
|
@ -214,18 +234,24 @@ if __name__ == "__main__":
|
|
|
|
|
for item in selected_files:
|
|
|
|
|
add_watermask(item, water_path)
|
|
|
|
|
# 删除临时PDF印章
|
|
|
|
|
if tmp_water != '':
|
|
|
|
|
if tmp_water != "":
|
|
|
|
|
os.remove(tmp_water)
|
|
|
|
|
tmp_water = ''
|
|
|
|
|
tmp_water = ""
|
|
|
|
|
|
|
|
|
|
def open_dirname():
|
|
|
|
|
global last_stamped
|
|
|
|
|
dir_name = os.path.dirname(last_stamped)
|
|
|
|
|
os.startfile(dir_name)
|
|
|
|
|
if get_os == "Windows":
|
|
|
|
|
os.startfile(dir_name)
|
|
|
|
|
else:
|
|
|
|
|
subprocess.run(["open", dir_name])
|
|
|
|
|
|
|
|
|
|
def open_file():
|
|
|
|
|
global last_stamped
|
|
|
|
|
os.startfile(last_stamped)
|
|
|
|
|
if get_os == "Windows":
|
|
|
|
|
os.startfile(last_stamped)
|
|
|
|
|
else:
|
|
|
|
|
subprocess.run(["open", last_stamped])
|
|
|
|
|
|
|
|
|
|
def get_path(relative_path):
|
|
|
|
|
try:
|
|
|
|
|
@ -257,38 +283,42 @@ if __name__ == "__main__":
|
|
|
|
|
root.geometry("{}x{}+{}+{}".format(500, 300, x_pos, y_pos))
|
|
|
|
|
# 选择文件-多选
|
|
|
|
|
button_files = Button(root, text="选择文件", command=select_files)
|
|
|
|
|
button_files.place(x=button_x, y=padding_y, width=button_width,
|
|
|
|
|
height=button_height)
|
|
|
|
|
button_files.place(
|
|
|
|
|
x=button_x, y=padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
lable_files = Label(root, text="")
|
|
|
|
|
lable_files.place(x=label_x, y=padding_y,
|
|
|
|
|
width=label_width, height=lable_height)
|
|
|
|
|
lable_files.place(x=label_x, y=padding_y, width=label_width, height=lable_height)
|
|
|
|
|
# 选择目录
|
|
|
|
|
button_dir = Button(root, text="选择目录", command=select_dir)
|
|
|
|
|
button_dir.place(x=button_x, y=2*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
button_dir.place(
|
|
|
|
|
x=button_x, y=2 * padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
lable_dir = Label(root, text="")
|
|
|
|
|
lable_dir.place(x=label_x, y=2*padding_y,
|
|
|
|
|
width=label_width, height=lable_height)
|
|
|
|
|
lable_dir.place(x=label_x, y=2 * padding_y, width=label_width, height=lable_height)
|
|
|
|
|
# 选择公章
|
|
|
|
|
button_stamp = Button(root, text="选择公章", command=lambda: select_file(lable_stamp,
|
|
|
|
|
extensions=['png', 'jpeg', 'jpg']))
|
|
|
|
|
button_stamp.place(x=button_x, y=3*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
lable_stamp = Label(root, text=get_path('waters/stamp.png'))
|
|
|
|
|
lable_stamp.place(x=label_x, y=3*padding_y,
|
|
|
|
|
width=label_width, height=lable_height)
|
|
|
|
|
button_stamp = Button(
|
|
|
|
|
root,
|
|
|
|
|
text="选择公章",
|
|
|
|
|
command=lambda: select_file(lable_stamp, extensions=["png", "jpeg", "jpg"]),
|
|
|
|
|
)
|
|
|
|
|
button_stamp.place(
|
|
|
|
|
x=button_x, y=3 * padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
lable_stamp = Label(root, text=get_path("waters/stamp.png"))
|
|
|
|
|
lable_stamp.place(
|
|
|
|
|
x=label_x, y=3 * padding_y, width=label_width, height=lable_height
|
|
|
|
|
)
|
|
|
|
|
# 预览
|
|
|
|
|
label_create = Label(root, text="")
|
|
|
|
|
button_opendir = Button(root, text="目录", command=open_dirname)
|
|
|
|
|
button_openfile = Button(root, text="预览", command=open_file)
|
|
|
|
|
# 添加水印
|
|
|
|
|
button_create = Button(
|
|
|
|
|
root, text="生成", command=multi_watermask, state='disabled')
|
|
|
|
|
button_create.place(x=120, y=6*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
button_create = Button(root, text="生成", command=multi_watermask, state="disabled")
|
|
|
|
|
button_create.place(
|
|
|
|
|
x=120, y=6 * padding_y, width=button_width, height=button_height
|
|
|
|
|
)
|
|
|
|
|
# 重置
|
|
|
|
|
button_reset = Button(root, text="重置", command=reset)
|
|
|
|
|
button_reset.place(x=320, y=6*padding_y,
|
|
|
|
|
width=button_width, height=button_height)
|
|
|
|
|
button_reset.place(x=320, y=6 * padding_y, width=button_width, height=button_height)
|
|
|
|
|
|
|
|
|
|
root.mainloop()
|