acdr/acdr-ui/tootls/图片截取位置.py

127 lines
5.3 KiB
Python
Raw Normal View History

2024-09-19 01:44:07 +08:00
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("<Button-1>", self.start_selection)
self.canvas.bind("<B1-Motion>", self.update_selection)
self.canvas.bind("<ButtonRelease-1>", 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()