import tkinter as tk from tkinter import filedialog, messagebox from PIL import Image, ImageTk import os class ImageCropApp: def __init__(self, root): self.root = root self.root.title("Multi Image Crop Tool") # 选择图片按钮 self.select_button = tk.Button(root, text="选择图片", command=self.select_images) self.select_button.pack(pady=10) # 画布,用于显示图片 self.canvas = tk.Canvas(root, cursor="cross") self.canvas.pack(fill=tk.BOTH, expand=True) self.images = [] # 用于保存选择的多张图片路径 self.image = None # 当前显示的图片 self.rect_start_x = 0 self.rect_start_y = 0 self.rect_end_x = 0 self.rect_end_y = 0 self.rect = None self.tk_image = None self.save_dir = None # 保存路径 self.image_display_width = 0 # 显示图片的宽度 self.image_display_height = 0 # 显示图片的高度 self.image_original_width = 0 # 图片的原始宽度 self.image_original_height = 0 # 图片的原始高度 # 鼠标事件 self.canvas.bind("", self.start_selection) self.canvas.bind("", self.update_selection) self.canvas.bind("", self.finish_selection) def select_images(self): # 多文件选择 image_paths = filedialog.askopenfilenames(title="选择多张图片", filetypes=[("Image files", "*.jpg;*.png;*.jpeg;*.bmp"), ("All files", "*.*")]) if image_paths: self.images = list(image_paths) # 将文件路径保存为列表 self.load_first_image() def load_first_image(self): # 加载第一张图片并显示在画布上 if self.images: self.image = Image.open(self.images[0]) self.image_original_width, self.image_original_height = self.image.size # 获取原始尺寸 self.display_image() def display_image(self): # 调整图片大小适应窗口 self.image.thumbnail((self.root.winfo_width(), self.root.winfo_height())) # 缩放图片 self.tk_image = ImageTk.PhotoImage(self.image) self.image_display_width, self.image_display_height = self.image.size # 显示的宽高 self.canvas.create_image(0, 0, anchor="nw", image=self.tk_image) def start_selection(self, event): # 记录起始点 self.rect_start_x = event.x self.rect_start_y = event.y # 创建一个选择框 self.rect = self.canvas.create_rectangle(self.rect_start_x, self.rect_start_y, self.rect_start_x, self.rect_start_y, outline="red", width=2) def update_selection(self, event): # 更新选择框大小 self.rect_end_x = event.x self.rect_end_y = event.y self.canvas.coords(self.rect, self.rect_start_x, self.rect_start_y, self.rect_end_x, self.rect_end_y) def finish_selection(self, event): self.rect_end_x = event.x self.rect_end_y = event.y self.crop_images() def crop_images(self): if self.images: # 计算图像与显示窗口的比例 x_ratio = self.image_original_width / self.image_display_width y_ratio = self.image_original_height / self.image_display_height # 获取选择框的坐标,并转换为图片的实际坐标 left = min(self.rect_start_x, self.rect_end_x) * x_ratio top = min(self.rect_start_y, self.rect_end_y) * y_ratio right = max(self.rect_start_x, self.rect_end_x) * x_ratio bottom = max(self.rect_start_y, self.rect_end_y) * y_ratio # 让用户选择保存文件夹,只选择一次 if self.save_dir is None: self.save_dir = filedialog.askdirectory(title="选择保存文件夹") if not self.save_dir: messagebox.showwarning("警告", "未选择保存文件夹,操作已取消") return for image_path in self.images: img = Image.open(image_path) img_original_width, img_original_height = img.size # 获取每张图片的原始大小 # 根据比例缩放选择区域并裁剪 left_scaled = left * (img_original_width / self.image_original_width) top_scaled = top * (img_original_height / self.image_original_height) right_scaled = right * (img_original_width / self.image_original_width) bottom_scaled = bottom * (img_original_height / self.image_original_height) cropped_image = img.crop((left_scaled, top_scaled, right_scaled, bottom_scaled)) # 自动生成默认文件名 base_name = os.path.basename(image_path) default_filename = f"cropped_{base_name}" # 保存路径与文件名 save_path = os.path.join(self.save_dir, default_filename) cropped_image.save(save_path) print(f"图片已保存到: {save_path}") messagebox.showinfo("成功", "所有图片裁剪完成!") # 启动 GUI 应用 if __name__ == "__main__": root = tk.Tk() app = ImageCropApp(root) root.geometry("800x600") # 设置初始窗口大小 root.mainloop()