首页 > 编程语言 >【Python自制工具软件】批量图片转PDF小工具——PIC2PDF

【Python自制工具软件】批量图片转PDF小工具——PIC2PDF

时间:2023-07-02 22:01:11浏览次数:51  
标签:files 工具软件 Python PIC2PDF width file path folder png

楔子

大家在工作当中总会冒出各种各样的需求,尤其当面对繁琐的工作时。

“如果有那样一款想象中的工具就好了!”可以瞬间解决手头工作的想象中的工具,是否存在呢?

当然,然而获得它总是需要我们花费大量的时间去筛选甄别,有的充斥大量广告,有的则需要付出不菲的费用。

其实完全可以自己上手来实现自己想象出的功能,做出适合自己使用的软件。过程中也可以一步一步不停的完善,将它当作一款产品去打磨。

这样有成就感的事情,其实用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 安装 PyinstallerPILwindnd 成功后即可进行打包

[END]

标签:files,工具软件,Python,PIC2PDF,width,file,path,folder,png
From: https://www.cnblogs.com/dmcs95/p/17521508.html

相关文章

  • Python | 文件处理
    文件的读写文件对象在python中用open()可以创建一个文件对象。open()使用方法:open(file,mode='r',buffering=-1,encoding=None,errors=None,newline=None,closefd=True,opener=None)参数说明:file:必需,文件路径(相对或者绝对路径)。mode:可选,文件打开模式(常用)buf......
  • Google Colab:云端的Python编程神器
    GoogleColab,全名GoogleColaboratory,是GoogleResearch团队开发的一款云端编程工具,它允许任何人通过浏览器编写和执行Python代码。Colab尤其适合机器学习、数据分析和教育目的。它是一种托管式Jupyter笔记本服务,用户无需设置,就可以直接使用,同时还能获得GPU等计算资源的免费使用......
  • Python | with关键字详解
    with使用背景对于系统资源如文件、数据库连接、socket而言,应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(释放)该资源。比如Python程序打开一个文件,往文件中写内容,写完之后,就要关闭该文件,如果不关闭会出现什么情况呢?极端情况下会出现Toomanyopenfiles......
  • python: multiple inheritance
    多继承"""Mother.py多继承类inheritedAnimalpython(类名)superjava继承可以使用extends和implements这两个关键字来实现继承C++:public类名C#:类名可以重写父类方法edit:geovindu,GeovinDudate:20230702IDE:PyCharm2023.1.2"""importsysimportosi......
  • python中globals()的用法
    python中globals()的用法 1.获取所有的全局变量,获取到的内容如下:{'__name__':'__main__','__doc__':None,'__package__':None,'__loader__':<_frozen_importlib_external.SourceFileLoaderobjectat0x7efc4bd1d960>,�......
  • Python入门
    一、逻辑运算符的一些记录#非布尔值的与或运算#当我们对非布尔值进行与或运算时,Python会将其当做布尔值运算,最终会返回原值#与运算的规则#与运算是找False的,如果第一个值是False,则不看第二个值#如果第一个值是False,则直接返回第一个值,否则返回第二个值#或......
  • Python - 编写Unicode 字符串
    Python的字符串字面量支持"\xNN"十六进制字节值转义以及"\uNNNN"和"\UNNNNNNNN"Unicode转义。第一种形式用4位十六进制数编码2字节(16位)位字符码点第二种形式用8位十六进制数编码4字节(32位)码点。十六进制值0xCD和0xE8,是ASCII的7位字符范围之外的两个特殊的声调字符......
  • Python 满足列中任意两个数之和等于目标值,输出这两个数的值和所在列表的索引值
    给定一个列表为nums=[2,7,11,15],目标值target=9,找出列表中任意2数之和等于9的元素以及所在位置思路:双重遍历去一对一的比较判断1nums=[2,7,11,15,1,8,2]2target=93list_new=[]4deffind_num_indx():56foriinrange(len(nums)):......
  • python 字典key单引号变双引号
    背景:str1="{'a':1,'b':2,'c':3}"把字典格式的字符串str1转成字典importjsons_dic=json.loads(str1)报错信息:json.decoder.JSONDecodeError:Expectingpropertynameenclosedindoublequotes:line1column2(char1) 解决思路:方法一:(不建......
  • Python 找出一个字符串出现3次的元素
    方式一:利用字典中key唯一来判断存在时,计数统计给value,不存在时,赋值value为1A='aabbcccdddd'B={}foriinA:ifiinB:#直接判断key在不在字典中B[i]+=1else:B[i]=1print(B)print(B) 方式二:用count去统计......