python 对图片增加边框,logo贴图,获取图片exif参数,填写图片文本内容-CSDN博客
import tkinter as tk
from tkinter import ttk
import os
import glob
import json
import tkinter.messagebox as messagebox # 弹出提示框
from PIL import Image, ImageDraw, ImageFont
import exifread
def photo_exif(image_path):
f = open(image_path, 'rb')
tags = exifread.process_file(f)
# 打印所有照片信息,会以键值对的方法保存
# for tag in tags.keys():
# print("Key: {0}, value {1}".format(tag, tags[tag]))
# print(str(tags['EXIF FocalLength']) + 'mm', tags['EXIF ExposureTime'], 'ISO' + str(tags['EXIF ISOSpeedRatings']))
return tags
def add_logo_with_text(image_path, logo_path, logo_size, text1, text2, text3, font_path, font_size, font_color, border_size,
border_color, output_path):
# 打开原始图片
image = Image.open(image_path).convert("RGB")
width, height = image.size
# 计算边框区域大小和位置
font = ImageFont.truetype(font_path, font_size)
text1_width, text1_height = font.getsize(text1)
text2_width, text2_height = font.getsize(text2)
text3_width, text3_height = font.getsize(text3)
text_width = max(text1_width, text2_width, text3_width)
text_height = text1_height + text2_height + text3_height
border_width = logo_size[0] + text_width + border_size * 3
border_height = max(logo_size[1], text_height) + border_size * 2
border_position = ((width - border_width) // 2, height)
# 打开logo图片并调整大小
logo = Image.open(logo_path).resize(logo_size, Image.ANTIALIAS)
# 创建新的图片
new_width = width
new_height = height + border_height
new_image = Image.new("RGB", (new_width, new_height), "white")
# 将原始图片复制到新图片的顶部
new_image.paste(image, (0, 0, width, height))
# 在新图片上绘制边框
draw = ImageDraw.Draw(new_image)
border_rect = (border_position[0], height, border_position[0] + border_width, height + border_height)
draw.rectangle(border_rect, fill=None, outline=border_color, width=border_size)
# 在边框区域内绘制logo图片
logo_position = (border_position[0] + border_size, height + (border_height - logo_size[1]) // 2)
new_image.paste(logo, logo_position)
# 在边框区域内绘制文本
text1_position = (border_position[0] + border_size * 2 + logo_size[0], height + (border_height - text_height) // 2)
text2_position = (border_position[0] + border_size * 2 + logo_size[0], text1_position[1] + text1_height)
text3_position = (border_position[0] + border_size * 2 + logo_size[0], text2_position[1] + text2_height)
draw.text(text1_position, text1, font=font, fill=font_color)
draw.text(text2_position, text2, font=font, fill=font_color)
draw.text(text3_position, text3, font=font, fill=font_color)
# 保存合成后的图片
new_image.save(output_path)
def generate_callback():
# 获取下拉列表的选中值
param1 = combo1.get()
param2 = combo2.get()
param3 = combo3.get()
param4 = combo4.get()
param5 = combo5.get()
param6 = combo6.get()
param66 = combo66.get()
param7 = combo7.get()
# 判断输入是否为空,弹出提示框
if not param1:
messagebox.showerror("Error", "图片路径不能为空!")
return
if not param2:
messagebox.showerror("Error", "Logo路径不能为空!")
return
if not param3:
messagebox.showerror("Error", "参数1不能为空!")
return
if not param4:
messagebox.showerror("Error", "参数2不能为空!")
return
if not param5:
messagebox.showerror("Error", "参数3不能为空!")
return
if not param6:
messagebox.showerror("Error", "字体路径不能为空!")
return
if not param66:
messagebox.showerror("Error", "字体大小不能为空!")
return
if not param7:
messagebox.showerror("Error", "输出路径不能为空!")
return
# 调用后端处理函数,并传递参数
# print(param1, param2, param22, param3, param4, param5, param6, param66, param7)
# 示例用法
# 照片路径
image_path = param1
# logo图片路径
logo_path = param2
# logo图片大小
logo_size = (255, 255)
# 图片信息
tags = photo_exif(image_path)
text1 = param3
text2 = param4
text3 = param5
# 字体路径
font_path = param6
font_size = 55
font_color = (0, 0, 0) # 黑色
border_size = 55
border_color = (255, 255, 255) # 白色
# 输出照片 .后缀为png为无损图片 ,jpg为压缩后的图片
output_path = str(image_path)+str(param7)
add_logo_with_text(image_path, logo_path, logo_size, text1, text2, text3, font_path, font_size, font_color, border_size,
border_color, output_path)
print("图片已保存至:", output_path)
messagebox.showinfo("提示", "图片已保存至:\n" + output_path)
def on_file_list_double_click(event):
selected_index = event.widget.curselection()
if selected_index:
selected_file = event.widget.get(selected_index)
combo1.set(selected_file)
def on_logo_list_double_click(event):
selected_index = event.widget.curselection()
if selected_index:
selected_file = event.widget.get(selected_index)
combo2.set(selected_file)
def on_font_list_double_click(event):
selected_index = event.widget.curselection()
if selected_index:
selected_file = event.widget.get(selected_index)
combo6.set(selected_file)
# 创建主窗口
root = tk.Tk()
# 读取json文件参数
f = open('config.json', 'r', encoding='utf-8')
content = f.read()
a = json.loads(content)
# 创建参数名称和下拉列表的组件
label1 = tk.Label(root, text="图片路径:")
combo1 = ttk.Combobox(root, state="normal", values=a["param1"])
label2 = tk.Label(root, text="logo路径:")
combo2 = ttk.Combobox(root, state="normal", values=a["param2"])
label3 = tk.Label(root, text="参数1:")
combo3 = ttk.Combobox(root, state="normal", values=a["param3"])
label4 = tk.Label(root, text="参数2:")
combo4 = ttk.Combobox(root, state="normal", values=a["param4"])
label5 = tk.Label(root, text="参数3:")
combo5 = ttk.Combobox(root, state="normal", values=a["param5"])
label6 = tk.Label(root, text="字体路径:")
combo6 = ttk.Combobox(root, state="normal", values=a["param6"])
label66 = tk.Label(root, text="字体大小:")
combo66 = ttk.Combobox(root, state="normal", values=a["param66"])
label7 = tk.Label(root, text="输出路径:")
combo7 = ttk.Combobox(root, state="normal", values=a["param7"])
# label7 = tk.Label(root, text="输出路径:")
# combo7 = ttk.Combobox(root, state="normal", values=["选项1", "选项2", "选项3"])
# 设置下拉框的高度和宽度
combo1.configure(width=68)
combo2.configure(width=68)
combo3.configure(width=68)
combo4.configure(width=68)
combo5.configure(width=68)
combo6.configure(width=68)
combo66.configure(width=68)
combo7.configure(width=68)
# 创建生成按钮并绑定回调函数
generate_btn = tk.Button(text="生成", command=generate_callback ,width=79 ,height=2)
# 使用grid布局来放置各个组件
label1.grid(row=0, column=0)
combo1.grid(row=0, column=1)
label2.grid(row=1, column=0)
combo2.grid(row=1, column=1)
label3.grid(row=2, column=0)
combo3.grid(row=2, column=1)
label4.grid(row=3, column=0)
combo4.grid(row=3, column=1)
label5.grid(row=4, column=0)
combo5.grid(row=4, column=1)
label6.grid(row=5, column=0)
combo6.grid(row=5, column=1)
label66.grid(row=6, column=0)
combo66.grid(row=6, column=1)
label7.grid(row=7, column=0)
combo7.grid(row=7, column=1)
generate_btn.grid(row=8, columnspan=2) # 使用columnspan设置按钮横跨两列
# 设置默认选中值
combo1.current(0)
combo2.current(0)
combo3.current(0)
combo4.current(0)
combo5.current(0)
combo6.current(0)
combo66.current(0)
combo7.current(0)
# 添加标题
title_label = tk.Label(root, text="文件路径:")
title_label.grid(row=0, column=2, sticky="w")
# 添加标题
logo_title_label = tk.Label(root, text="Logo路径:")
logo_title_label.grid(row=0, column=4, sticky="w")
font_title_label = tk.Label(root, text="字体路径:")
font_title_label.grid(row=0, column=6, sticky="w")
# 获取当前py文件目录下的所有文件路径
file_paths = glob.glob('*')
# 创建文件路径列表框组件
file_listbox_var = tk.StringVar(value=file_paths)
file_listbox = tk.Listbox(root, listvariable=file_listbox_var)
file_listbox.grid(row=1, column=2, rowspan=7, padx=10, pady=10, sticky="nsew")
# 绑定双击事件处理函数
file_listbox.bind('', on_file_list_double_click)
# 设置列表框自动填充满父容器
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(2, weight=1)
# 创建滚动条
file_scrollbar = tk.Scrollbar(root, orient="vertical", command=file_listbox.yview)
file_scrollbar.grid(row=1, column=3, rowspan=7, sticky="ns")
# 将滚动条与文件路径列表框关联
file_listbox.configure(yscrollcommand=file_scrollbar.set)
# 创建logo路径列表框组件
logo_listbox_var = tk.StringVar(value=file_paths)
logo_listbox = tk.Listbox(root, listvariable=logo_listbox_var)
logo_listbox.grid(row=1, column=4, rowspan=7, padx=10, pady=10, sticky="nsew")
# 绑定双击事件处理函数
logo_listbox.bind('', on_logo_list_double_click)
# 创建滚动条
logo_scrollbar = tk.Scrollbar(root, orient="vertical", command=logo_listbox.yview)
logo_scrollbar.grid(row=1, column=5, rowspan=7, sticky="ns")
# 将滚动条与logo路径列表框关联
logo_listbox.configure(yscrollcommand=logo_scrollbar.set)
# 创建字体路径列表框组件
font_listbox_var = tk.StringVar(value=file_paths)
font_listbox = tk.Listbox(root, listvariable=font_listbox_var)
font_listbox.grid(row=1, column=6, rowspan=7, padx=10, pady=10, sticky="nsew")
# 绑定双击事件处理函数
font_listbox.bind('', on_font_list_double_click)
# 创建滚动条
font_scrollbar = tk.Scrollbar(root, orient="vertical", command=font_listbox.yview)
font_scrollbar.grid(row=1, column=7, rowspan=7, sticky="ns")
# 将滚动条与字体路径列表框关联
font_listbox.configure(yscrollcommand=font_scrollbar.set)
#
# root.geometry("900x400") # 设置窗口的宽度为600个像素,高度为400个像素
# 运行主循环
root.mainloop()