• python 图片下面加边框TK界面


    python 对图片增加边框,logo贴图,获取图片exif参数,填写图片文本内容-CSDN博客

    1. import tkinter as tk
    2. from tkinter import ttk
    3. import os
    4. import glob
    5. import json
    6. import tkinter.messagebox as messagebox # 弹出提示框
    7. from PIL import Image, ImageDraw, ImageFont
    8. import exifread
    9. def photo_exif(image_path):
    10. f = open(image_path, 'rb')
    11. tags = exifread.process_file(f)
    12. # 打印所有照片信息,会以键值对的方法保存
    13. # for tag in tags.keys():
    14. # print("Key: {0}, value {1}".format(tag, tags[tag]))
    15. # print(str(tags['EXIF FocalLength']) + 'mm', tags['EXIF ExposureTime'], 'ISO' + str(tags['EXIF ISOSpeedRatings']))
    16. return tags
    17. def add_logo_with_text(image_path, logo_path, logo_size, text1, text2, text3, font_path, font_size, font_color, border_size,
    18. border_color, output_path):
    19. # 打开原始图片
    20. image = Image.open(image_path).convert("RGB")
    21. width, height = image.size
    22. # 计算边框区域大小和位置
    23. font = ImageFont.truetype(font_path, font_size)
    24. text1_width, text1_height = font.getsize(text1)
    25. text2_width, text2_height = font.getsize(text2)
    26. text3_width, text3_height = font.getsize(text3)
    27. text_width = max(text1_width, text2_width, text3_width)
    28. text_height = text1_height + text2_height + text3_height
    29. border_width = logo_size[0] + text_width + border_size * 3
    30. border_height = max(logo_size[1], text_height) + border_size * 2
    31. border_position = ((width - border_width) // 2, height)
    32. # 打开logo图片并调整大小
    33. logo = Image.open(logo_path).resize(logo_size, Image.ANTIALIAS)
    34. # 创建新的图片
    35. new_width = width
    36. new_height = height + border_height
    37. new_image = Image.new("RGB", (new_width, new_height), "white")
    38. # 将原始图片复制到新图片的顶部
    39. new_image.paste(image, (0, 0, width, height))
    40. # 在新图片上绘制边框
    41. draw = ImageDraw.Draw(new_image)
    42. border_rect = (border_position[0], height, border_position[0] + border_width, height + border_height)
    43. draw.rectangle(border_rect, fill=None, outline=border_color, width=border_size)
    44. # 在边框区域内绘制logo图片
    45. logo_position = (border_position[0] + border_size, height + (border_height - logo_size[1]) // 2)
    46. new_image.paste(logo, logo_position)
    47. # 在边框区域内绘制文本
    48. text1_position = (border_position[0] + border_size * 2 + logo_size[0], height + (border_height - text_height) // 2)
    49. text2_position = (border_position[0] + border_size * 2 + logo_size[0], text1_position[1] + text1_height)
    50. text3_position = (border_position[0] + border_size * 2 + logo_size[0], text2_position[1] + text2_height)
    51. draw.text(text1_position, text1, font=font, fill=font_color)
    52. draw.text(text2_position, text2, font=font, fill=font_color)
    53. draw.text(text3_position, text3, font=font, fill=font_color)
    54. # 保存合成后的图片
    55. new_image.save(output_path)
    56. def generate_callback():
    57. # 获取下拉列表的选中值
    58. param1 = combo1.get()
    59. param2 = combo2.get()
    60. param3 = combo3.get()
    61. param4 = combo4.get()
    62. param5 = combo5.get()
    63. param6 = combo6.get()
    64. param66 = combo66.get()
    65. param7 = combo7.get()
    66. # 判断输入是否为空,弹出提示框
    67. if not param1:
    68. messagebox.showerror("Error", "图片路径不能为空!")
    69. return
    70. if not param2:
    71. messagebox.showerror("Error", "Logo路径不能为空!")
    72. return
    73. if not param3:
    74. messagebox.showerror("Error", "参数1不能为空!")
    75. return
    76. if not param4:
    77. messagebox.showerror("Error", "参数2不能为空!")
    78. return
    79. if not param5:
    80. messagebox.showerror("Error", "参数3不能为空!")
    81. return
    82. if not param6:
    83. messagebox.showerror("Error", "字体路径不能为空!")
    84. return
    85. if not param66:
    86. messagebox.showerror("Error", "字体大小不能为空!")
    87. return
    88. if not param7:
    89. messagebox.showerror("Error", "输出路径不能为空!")
    90. return
    91. # 调用后端处理函数,并传递参数
    92. # print(param1, param2, param22, param3, param4, param5, param6, param66, param7)
    93. # 示例用法
    94. # 照片路径
    95. image_path = param1
    96. # logo图片路径
    97. logo_path = param2
    98. # logo图片大小
    99. logo_size = (255, 255)
    100. # 图片信息
    101. tags = photo_exif(image_path)
    102. text1 = param3
    103. text2 = param4
    104. text3 = param5
    105. # 字体路径
    106. font_path = param6
    107. font_size = 55
    108. font_color = (0, 0, 0) # 黑色
    109. border_size = 55
    110. border_color = (255, 255, 255) # 白色
    111. # 输出照片 .后缀为png为无损图片 ,jpg为压缩后的图片
    112. output_path = str(image_path)+str(param7)
    113. add_logo_with_text(image_path, logo_path, logo_size, text1, text2, text3, font_path, font_size, font_color, border_size,
    114. border_color, output_path)
    115. print("图片已保存至:", output_path)
    116. messagebox.showinfo("提示", "图片已保存至:\n" + output_path)
    117. def on_file_list_double_click(event):
    118. selected_index = event.widget.curselection()
    119. if selected_index:
    120. selected_file = event.widget.get(selected_index)
    121. combo1.set(selected_file)
    122. def on_logo_list_double_click(event):
    123. selected_index = event.widget.curselection()
    124. if selected_index:
    125. selected_file = event.widget.get(selected_index)
    126. combo2.set(selected_file)
    127. def on_font_list_double_click(event):
    128. selected_index = event.widget.curselection()
    129. if selected_index:
    130. selected_file = event.widget.get(selected_index)
    131. combo6.set(selected_file)
    132. # 创建主窗口
    133. root = tk.Tk()
    134. # 读取json文件参数
    135. f = open('config.json', 'r', encoding='utf-8')
    136. content = f.read()
    137. a = json.loads(content)
    138. # 创建参数名称和下拉列表的组件
    139. label1 = tk.Label(root, text="图片路径:")
    140. combo1 = ttk.Combobox(root, state="normal", values=a["param1"])
    141. label2 = tk.Label(root, text="logo路径:")
    142. combo2 = ttk.Combobox(root, state="normal", values=a["param2"])
    143. label3 = tk.Label(root, text="参数1:")
    144. combo3 = ttk.Combobox(root, state="normal", values=a["param3"])
    145. label4 = tk.Label(root, text="参数2:")
    146. combo4 = ttk.Combobox(root, state="normal", values=a["param4"])
    147. label5 = tk.Label(root, text="参数3:")
    148. combo5 = ttk.Combobox(root, state="normal", values=a["param5"])
    149. label6 = tk.Label(root, text="字体路径:")
    150. combo6 = ttk.Combobox(root, state="normal", values=a["param6"])
    151. label66 = tk.Label(root, text="字体大小:")
    152. combo66 = ttk.Combobox(root, state="normal", values=a["param66"])
    153. label7 = tk.Label(root, text="输出路径:")
    154. combo7 = ttk.Combobox(root, state="normal", values=a["param7"])
    155. # label7 = tk.Label(root, text="输出路径:")
    156. # combo7 = ttk.Combobox(root, state="normal", values=["选项1", "选项2", "选项3"])
    157. # 设置下拉框的高度和宽度
    158. combo1.configure(width=68)
    159. combo2.configure(width=68)
    160. combo3.configure(width=68)
    161. combo4.configure(width=68)
    162. combo5.configure(width=68)
    163. combo6.configure(width=68)
    164. combo66.configure(width=68)
    165. combo7.configure(width=68)
    166. # 创建生成按钮并绑定回调函数
    167. generate_btn = tk.Button(text="生成", command=generate_callback ,width=79 ,height=2)
    168. # 使用grid布局来放置各个组件
    169. label1.grid(row=0, column=0)
    170. combo1.grid(row=0, column=1)
    171. label2.grid(row=1, column=0)
    172. combo2.grid(row=1, column=1)
    173. label3.grid(row=2, column=0)
    174. combo3.grid(row=2, column=1)
    175. label4.grid(row=3, column=0)
    176. combo4.grid(row=3, column=1)
    177. label5.grid(row=4, column=0)
    178. combo5.grid(row=4, column=1)
    179. label6.grid(row=5, column=0)
    180. combo6.grid(row=5, column=1)
    181. label66.grid(row=6, column=0)
    182. combo66.grid(row=6, column=1)
    183. label7.grid(row=7, column=0)
    184. combo7.grid(row=7, column=1)
    185. generate_btn.grid(row=8, columnspan=2) # 使用columnspan设置按钮横跨两列
    186. # 设置默认选中值
    187. combo1.current(0)
    188. combo2.current(0)
    189. combo3.current(0)
    190. combo4.current(0)
    191. combo5.current(0)
    192. combo6.current(0)
    193. combo66.current(0)
    194. combo7.current(0)
    195. # 添加标题
    196. title_label = tk.Label(root, text="文件路径:")
    197. title_label.grid(row=0, column=2, sticky="w")
    198. # 添加标题
    199. logo_title_label = tk.Label(root, text="Logo路径:")
    200. logo_title_label.grid(row=0, column=4, sticky="w")
    201. font_title_label = tk.Label(root, text="字体路径:")
    202. font_title_label.grid(row=0, column=6, sticky="w")
    203. # 获取当前py文件目录下的所有文件路径
    204. file_paths = glob.glob('*')
    205. # 创建文件路径列表框组件
    206. file_listbox_var = tk.StringVar(value=file_paths)
    207. file_listbox = tk.Listbox(root, listvariable=file_listbox_var)
    208. file_listbox.grid(row=1, column=2, rowspan=7, padx=10, pady=10, sticky="nsew")
    209. # 绑定双击事件处理函数
    210. file_listbox.bind('', on_file_list_double_click)
    211. # 设置列表框自动填充满父容器
    212. root.grid_rowconfigure(1, weight=1)
    213. root.grid_columnconfigure(2, weight=1)
    214. # 创建滚动条
    215. file_scrollbar = tk.Scrollbar(root, orient="vertical", command=file_listbox.yview)
    216. file_scrollbar.grid(row=1, column=3, rowspan=7, sticky="ns")
    217. # 将滚动条与文件路径列表框关联
    218. file_listbox.configure(yscrollcommand=file_scrollbar.set)
    219. # 创建logo路径列表框组件
    220. logo_listbox_var = tk.StringVar(value=file_paths)
    221. logo_listbox = tk.Listbox(root, listvariable=logo_listbox_var)
    222. logo_listbox.grid(row=1, column=4, rowspan=7, padx=10, pady=10, sticky="nsew")
    223. # 绑定双击事件处理函数
    224. logo_listbox.bind('', on_logo_list_double_click)
    225. # 创建滚动条
    226. logo_scrollbar = tk.Scrollbar(root, orient="vertical", command=logo_listbox.yview)
    227. logo_scrollbar.grid(row=1, column=5, rowspan=7, sticky="ns")
    228. # 将滚动条与logo路径列表框关联
    229. logo_listbox.configure(yscrollcommand=logo_scrollbar.set)
    230. # 创建字体路径列表框组件
    231. font_listbox_var = tk.StringVar(value=file_paths)
    232. font_listbox = tk.Listbox(root, listvariable=font_listbox_var)
    233. font_listbox.grid(row=1, column=6, rowspan=7, padx=10, pady=10, sticky="nsew")
    234. # 绑定双击事件处理函数
    235. font_listbox.bind('', on_font_list_double_click)
    236. # 创建滚动条
    237. font_scrollbar = tk.Scrollbar(root, orient="vertical", command=font_listbox.yview)
    238. font_scrollbar.grid(row=1, column=7, rowspan=7, sticky="ns")
    239. # 将滚动条与字体路径列表框关联
    240. font_listbox.configure(yscrollcommand=font_scrollbar.set)
    241. #
    242. # root.geometry("900x400") # 设置窗口的宽度为600个像素,高度为400个像素
    243. # 运行主循环
    244. root.mainloop()

     

  • 相关阅读:
    PEFT学习:使用LORA进行LLM微调
    1.4-20:求一元二次方程的根
    java毕业设计在线测评系统2021Mybatis+系统+数据库+调试部署
    ArrayList的removeAll和retainAll方法
    力扣561. 数组拆分
    蓝牙ble自定义广播内容()
    数据库查询详解
    java使用ws.schild.jave将视频转成mp4
    CFdiv2-Tournament Countdown-(思维+交互题套路)
    必须收藏!没有经验的程序员该怎么找工作?
  • 原文地址:https://blog.csdn.net/qq_26086231/article/details/133874504