【Python自制工具软件】批量图片转PDF小工具——PIC2PDF
楔子
大家在工作当中总会冒出各种各样的需求,尤其当面对繁琐的工作时。
“如果有那样一款想象中的工具就好了!”可以瞬间解决手头工作的想象中的工具,是否存在呢?
当然,然而获得它总是需要我们花费大量的时间去筛选甄别,有的充斥大量广告,有的则需要付出不菲的费用。
其实完全可以自己上手来实现自己想象出的功能,做出适合自己使用的软件。过程中也可以一步一步不停的完善,将它当作一款产品去打磨。
这样有成就感的事情,其实用Python实现起来非常简单。
正好这段时间有整理照片的需求,于是就诞生了这样一款小工具。
虽然市面上很多这样类似的软件,但是自己做出来的也许更适合自己的使用习惯。
现在将代码附上,如有需要可以自行借鉴修改。
代码示例
import os
import datetime
import tkinter as tk
import tkinter.messagebox
import windnd
from tkinter import filedialog
from tkinter import ttk
from PIL import Image
# 预设转换后图片尺寸
width = 1920
height = 1080
root = tk.Tk()
root.geometry("300x120")
root.resizable(False, False)
root.title("PIC2PDF")
select_path = tk.StringVar()
width_ = tk.StringVar()
height_ = tk.StringVar()
width_.set("1920")
height_.set("1080")
dic = {"1920*1080":(1920, 1080),
"480*640": (480, 640),
"600*800": (600, 800),
"1024*768": (1024, 768),
"1152*864": (1152, 864),
"1280*600": (1280, 600)}
# 拖拽选择功能
def dragged_files(files):
msg = '\n'.join((item.decode('gbk') for item in files))
select_path.set(msg)
if msg != "":
tkinter.messagebox.showinfo("选择完成", msg)
else:
tkinter.messagebox.showwarning("警告","未选择文件!")
# 多选功能
def select_files():
select_files_path = filedialog.askopenfilenames()
select_path.set("\n".join(select_files_path))
if select_files_path != "":
tkinter.messagebox.showinfo("选择完成", "\n".join(select_files_path))
else:
tkinter.messagebox.showwarning("警告","未选择文件!")
# 文件夹选择功能
def select_folder():
folder_path = filedialog.askdirectory() + "/"
select_path.set(folder_path)
if folder_path != "/":
tkinter.messagebox.showinfo("选择完成", folder_path)
else:
tkinter.messagebox.showwarning("警告","未选择文件!")
def run():
try:
if (width_.get(), height_.get()) != dic[combobox.get()]:
global width, height
width = int(width_.get())
height = int(height_.get())
pdfFile = os.path.dirname(select_path.get().split("\n")[0]) + "/" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + ".pdf"
combine_imgs_pdf(select_path, pdfFile)
tkinter.messagebox.showinfo("提示","转换完成")
except (FileNotFoundError,IndexError):
tkinter.messagebox.showwarning("警告","未找到指定文件, 请重试!")
# 转换主功能函数
def combine_imgs_pdf(folder_path, pdf_file_path):
str_folder = folder_path.get()
if "\n" in str_folder or str_folder[-1] != "/":
str_folder_list = str_folder.split("\n")
png_files = []
sources = []
for file in str_folder_list:
if 'png' in file or 'jpg' in file or 'PNG' in file or 'JPG' in file:
old_pic = Image.open(file)
WIDTH, HEIGHT = old_pic.size
if HEIGHT > WIDTH:
old_pic = old_pic.transpose(Image.ROTATE_90)
new_image = old_pic.resize((width, height),Image.BILINEAR)
if "/" in file:
i = file.rfind("/")
else:
i = file.rfind("\\")
new_image.save(file[:i+1] + "small_" + file[i+1:])
png_files.append(file[:i+1] + "small_" + file[i+1:])
png_files.sort()
output = Image.open(png_files[0])
tmp = png_files.pop(0)
if png_files == []:
png_file = Image.open(tmp)
if png_file.mode == "RGBA":
png_file = png_file.convert("RGB")
output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)
png_file.close()
os.remove(tmp)
else:
for file in png_files:
png_file = Image.open(file)
if png_file.mode == "RGBA":
png_file = png_file.convert("RGB")
sources.append(png_file)
output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)
os.remove(file)
output.close()
os.remove(tmp)
else:
str_folder = folder_path.get()
files = os.listdir(str_folder)
png_files = []
sources = []
for file in files:
if 'png' in file or 'jpg' in file or 'PNG' in file or 'JPG' in file:
old_pic = Image.open(str_folder + file)
WIDTH, HEIGHT = old_pic.size
if HEIGHT > WIDTH:
old_pic = old_pic.transpose(Image.ROTATE_90)
new_image = old_pic.resize((width, height),Image.BILINEAR)
new_image.save(str_folder + "small_" + file)
png_files.append(str_folder + "small_" + file)
png_files.sort()
output = Image.open(png_files[0])
tmp = png_files.pop(0)
for file in png_files:
png_file = Image.open(file)
if png_file.mode == "RGBA":
png_file = png_file.convert("RGB")
sources.append(png_file)
output.save(pdf_file_path, "pdf", save_all=True, append_images=sources)
os.remove(file)
output.close()
os.remove(tmp)
# 尺寸选择回调函数
def callbackFunc(event):
global width, height
width, height = dic[combobox.get()]
width_.set(width)
height_.set(height)
lable = tk.Label(textvariable=tk.StringVar(value="支持文件拖拽(将根据文件名进行排序)\n图片尺寸支持自定义或选择预设尺寸\n(不建议小于原图尺寸,可能导致模糊无法辨识)"), cursor='arrow',justify="center", fg="red")
lable2 = tk.Label(textvariable=tk.StringVar(value="图片尺寸:"), cursor='arrow', justify="center")
lable3 = tk.Label(textvariable=tk.StringVar(value="*"), cursor='arrow', justify="center")
enter = tk.Entry(textvariable=width_, justify="center", relief="groove", width=5, highlightcolor="lightblue")
enter2 = tk.Entry(textvariable=height_, justify="center", relief="groove", width=5, highlightcolor="lightblue")
combobox = ttk.Combobox(root, values=["1920*1080","480*640","600*800","1024*768","1152*864","1280*600"], justify="center", state="readonly", width=10)
bt = tk.Button(text="选多文件", command=select_files, cursor='hand2', relief="groove")
bt2 = tk.Button(text="选文件夹", command=select_folder, cursor='hand2', relief="groove")
bt3 = tk.Button(text="开始转换", command=run, cursor='hand2', relief="groove", bg="lightblue")
# 控件定位
lable.place(x=14, y=0)
lable2.place(x=10, y=56)
enter.place(x=80, y=56)
lable3.place(x=118, y=56)
enter2.place(x=128, y=56)
combobox.place(x=196, y=55)
bt.place(x=10, y=84)
bt2.place(x=74, y=84)
bt3.place(x=230, y=84)
combobox.current(0)
combobox.bind("<<ComboboxSelected>>", callbackFunc)
windnd.hook_dropfiles(root, func=dragged_files)
root.mainloop()
所用第三方库均可使用 pip
进行安装
pip install pillow
pip install windnd
效果图
打包
如果想将其打包为单独的 exe 可执行文件可使用 Pyinstaller 通过以下命令实现
pyinstaller -F -w -i favicon.ico -n PIC2PDF main.py
安装 Pyinstaller
pip install Pyinstaller
创建虚拟环境
打包时请使用纯净的虚拟环境来减小打包后文件大小,可通过如下操作创建虚拟环境
在 Windows 系统下
1、通过 pip install virtualenv
安装创建虚拟环境所需要的第三方库
2、通过 virtualenv env_name
创建名为 env_name
的虚拟环境,虚拟环境将创建到当前目录下
3、激活虚拟环境:找到 env_name/Scripts/
目录下 activate
执行,在命令行中,当前输入行前将会有 env_name
前缀表明已进入虚拟环境
4、在虚拟环境中通过 pip
安装 Pyinstaller
、PIL
、windnd
成功后即可进行打包
[END]