Python adds borders and logo textures to images, obtains image exif parameters, and fills in image text content – CSDN Blog
import tkinter as tk from tkinter import ttk import os import glob import json import tkinter.messagebox as messagebox # Pop up prompt box from PIL import Image, ImageDraw, ImageFont import exifread def photo_exif(image_path): f = open(image_path, 'rb') tags = exifread.process_file(f) # Print all photo information and save it as key-value pairs # 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): #Open the original image image = Image.open(image_path).convert("RGB") width, height = image.size # Calculate the size and position of the border area 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) # Open the logo image and resize it logo = Image.open(logo_path).resize(logo_size, Image.ANTIALIAS) #Create new image new_width = width new_height = height + border_height new_image = Image.new("RGB", (new_width, new_height), "white") # Copy the original image to the top of the new image new_image.paste(image, (0, 0, width, height)) # Draw a border on the new image 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) # Draw the logo image in the border area logo_position = (border_position[0] + border_size, height + (border_height - logo_size[1]) // 2) new_image.paste(logo, logo_position) # Draw text within the border area 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) # Save the synthesized image new_image.save(output_path) def generate_callback(): # Get the selected value of the drop-down list param1 = combo1.get() param2 = combo2.get() param3 = combo3.get() param4 = combo4.get() param5 = combo5.get() param6 = combo6.get() param66 = combo66.get() param7 = combo7.get() # Determine whether the input is empty and pop up a prompt box if not param1: messagebox.showerror("Error", "The image path cannot be empty!") return if not param2: messagebox.showerror("Error", "Logo path cannot be empty!") return if not param3: messagebox.showerror("Error", "Parameter 1 cannot be empty!") return if not param4: messagebox.showerror("Error", "Parameter 2 cannot be empty!") return if not param5: messagebox.showerror("Error", "Parameter 3 cannot be empty!") return if not param6: messagebox.showerror("Error", "Font path cannot be empty!") return if not param66: messagebox.showerror("Error", "Font size cannot be empty!") return if not param7: messagebox.showerror("Error", "The output path cannot be empty!") return # Call the backend processing function and pass parameters # print(param1, param2, param22, param3, param4, param5, param6, param66, param7) # Example usage # photo path image_path = param1 # logo image path logo_path = param2 # Logo image size logo_size = (255, 255) # image information tags = photo_exif(image_path) text1 = param3 text2 = param4 text3 = param5 # Font path font_path = param6 font_size = 55 font_color = (0, 0, 0) # black border_size = 55 border_color = (255, 255, 255) # white # Output photos. The suffix is png for lossless images and jpg for compressed images. 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("The picture has been saved to:", output_path) messagebox.showinfo("Prompt", "The picture has been saved to: \\ " + 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) #Create the main window root = tk.Tk() #Read json file parameters f = open('config.json', 'r', encoding='utf-8') content = f.read() a = json.loads(content) # Create components with parameter names and drop-down lists label1 = tk.Label(root, text="Picture path:") combo1 = ttk.Combobox(root, state="normal", values=a["param1"]) label2 = tk.Label(root, text="logo path:") combo2 = ttk.Combobox(root, state="normal", values=a["param2"]) label3 = tk.Label(root, text="Parameter 1:") combo3 = ttk.Combobox(root, state="normal", values=a["param3"]) label4 = tk.Label(root, text="Parameter 2:") combo4 = ttk.Combobox(root, state="normal", values=a["param4"]) label5 = tk.Label(root, text="Parameter 3:") combo5 = ttk.Combobox(root, state="normal", values=a["param5"]) label6 = tk.Label(root, text="Font path:") combo6 = ttk.Combobox(root, state="normal", values=a["param6"]) label66 = tk.Label(root, text="Font size:") combo66 = ttk.Combobox(root, state="normal", values=a["param66"]) label7 = tk.Label(root, text="Output path:") combo7 = ttk.Combobox(root, state="normal", values=a["param7"]) # label7 = tk.Label(root, text="Output path:") # combo7 = ttk.Combobox(root, state="normal", values=["Option 1", "Option 2", "Option 3"]) #Set the height and width of the drop-down box 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) #Create a generate button and bind a callback function generate_btn = tk.Button(text="Generate", command=generate_callback, width=79, height=2) # Use grid layout to place each component 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) # Use columnspan to set the button to span two columns #Set the default selected value combo1.current(0) combo2.current(0) combo3.current(0) combo4.current(0) combo5.current(0) combo6.current(0) combo66.current(0) combo7.current(0) #Add title title_label = tk.Label(root, text="File path:") title_label.grid(row=0, column=2, sticky="w") #Add title logo_title_label = tk.Label(root, text="Logo path:") logo_title_label.grid(row=0, column=4, sticky="w") font_title_label = tk.Label(root, text="Font path:") font_title_label.grid(row=0, column=6, sticky="w") # Get all file paths in the current py file directory file_paths = glob.glob('*') #Create file path list box component 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") # Bind the double-click event handler function file_listbox.bind('<Double-Button-1>', on_file_list_double_click) # Set the list box to automatically fill the parent container root.grid_rowconfigure(1, weight=1) root.grid_columnconfigure(2, weight=1) #Create scrollbar file_scrollbar = tk.Scrollbar(root, orient="vertical", command=file_listbox.yview) file_scrollbar.grid(row=1, column=3, rowspan=7, sticky="ns") #Associate the scroll bar with the file path list box file_listbox.configure(yscrollcommand=file_scrollbar.set) #Create the logo path list box component 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") # Bind the double-click event handler function logo_listbox.bind('<Double-Button-1>', on_logo_list_double_click) #Create scrollbar logo_scrollbar = tk.Scrollbar(root, orient="vertical", command=logo_listbox.yview) logo_scrollbar.grid(row=1, column=5, rowspan=7, sticky="ns") #Associate the scroll bar with the logo path list box logo_listbox.configure(yscrollcommand=logo_scrollbar.set) #Create font path list box component 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") # Bind the double-click event handler function font_listbox.bind('<Double-Button-1>', on_font_list_double_click) #Create scrollbar font_scrollbar = tk.Scrollbar(root, orient="vertical", command=font_listbox.yview) font_scrollbar.grid(row=1, column=7, rowspan=7, sticky="ns") #Associate the scroll bar with the font path list box font_listbox.configure(yscrollcommand=font_scrollbar.set) # # root.geometry("900x400") # Set the width of the window to 600 pixels and the height to 400 pixels #Run the main loop root.mainloop()