批量转灰度图和调整图片大小

python 复制代码
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image, ImageFilter, ImageEnhance
import os

class BatchImageProcessor:
    def __init__(self, root):
        self.root = root
        self.root.title("图片批量处理器")
        self.root.geometry("800x600")
        self.center_window()

        # 初始化变量
        self.input_folder = ""
        self.output_folder = ""
        self.processing_options = {
            "resize": False,
            "resize_width": 800,
            "resize_height": 600,
            "grayscale": False,
            "blur": False,
            "blur_radius": 2,
            "contrast": False,
            "contrast_factor": 1.2,
        }

        # 创建界面
        self.create_widgets()

    def center_window(self):
        # 强制更新窗口尺寸信息
        self.root.update_idletasks()

        # 获取窗口尺寸
        window_width = self.root.winfo_width()
        window_height = self.root.winfo_height()

        # 计算居中坐标
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2

        # 设置窗口位置
        self.root.geometry(f"+{x}+{y}")
    def create_widgets(self):
        # 顶部框架 - 文件夹选择
        folder_frame = tk.LabelFrame(self.root, text="文件夹设置", padx=10, pady=10)
        folder_frame.pack(fill="x", padx=10, pady=5)

        # 输入文件夹
        tk.Label(folder_frame, text="输入文件夹:").grid(row=0, column=0, sticky="w")
        self.input_entry = tk.Entry(folder_frame, width=50)
        self.input_entry.grid(row=0, column=1, padx=5)
        tk.Button(
            folder_frame,
            text="浏览...",
            command=self.select_input_folder
        ).grid(row=0, column=2)

        # 输出文件夹
        tk.Label(folder_frame, text="输出文件夹:").grid(row=1, column=0, sticky="w")
        self.output_entry = tk.Entry(folder_frame, width=50)
        self.output_entry.grid(row=1, column=1, padx=5)
        tk.Button(
            folder_frame,
            text="浏览...",
            command=self.select_output_folder
        ).grid(row=1, column=2)

        # 中间框架 - 处理选项
        option_frame = tk.LabelFrame(self.root, text="处理选项", padx=10, pady=10)
        option_frame.pack(fill="both", expand=True, padx=10, pady=5)

        # 调整大小选项
        self.resize_var = tk.BooleanVar()
        tk.Checkbutton(
            option_frame,
            text="调整大小",
            variable=self.resize_var,
            command=self.toggle_resize
        ).grid(row=0, column=0, sticky="w")

        self.resize_width_label = tk.Label(option_frame, text="宽度:")
        self.resize_width_label.grid(row=0, column=1, sticky="e")
        self.resize_width_entry = tk.Entry(option_frame, width=5)
        self.resize_width_entry.grid(row=0, column=2)
        self.resize_width_entry.insert(0, "800")

        tk.Label(option_frame, text="高度:").grid(row=0, column=3, sticky="e")
        self.resize_height_entry = tk.Entry(option_frame, width=5)
        self.resize_height_entry.grid(row=0, column=4)
        self.resize_height_entry.insert(0, "600")

        # 其他选项
        self.grayscale_var = tk.BooleanVar()
        tk.Checkbutton(
            option_frame,
            text="转为灰度图",
            variable=self.grayscale_var
        ).grid(row=1, column=0, sticky="w")

        self.blur_var = tk.BooleanVar()
        tk.Checkbutton(
            option_frame,
            text="模糊效果",
            variable=self.blur_var,
            command=self.toggle_blur
        ).grid(row=1, column=1, sticky="w")

        self.blur_radius_label = tk.Label(option_frame, text="模糊半径:")
        self.blur_radius_label.grid(row=1, column=2, sticky="e")
        self.blur_radius_entry = tk.Entry(option_frame, width=5)
        self.blur_radius_entry.grid(row=1, column=3)
        self.blur_radius_entry.insert(0, "2")

        self.contrast_var = tk.BooleanVar()
        tk.Checkbutton(
            option_frame,
            text="调整对比度",
            variable=self.contrast_var,
            command=self.toggle_contrast
        ).grid(row=2, column=0, sticky="w")

        self.contrast_label = tk.Label(option_frame, text="对比度系数:")
        self.contrast_label.grid(row=2, column=1, sticky="e")
        self.contrast_entry = tk.Entry(option_frame, width=5)
        self.contrast_entry.grid(row=2, column=2)
        self.contrast_entry.insert(0, "1.2")

        # 底部框架 - 操作按钮和进度条
        control_frame = tk.Frame(self.root)
        control_frame.pack(fill="x", padx=10, pady=5)

        tk.Button(
            control_frame,
            text="开始处理",
            command=self.start_processing,
            width=15
        ).pack(side="left", padx=5)

        tk.Button(
            control_frame,
            text="退出",
            command=self.root.quit,
            width=15
        ).pack(side="right", padx=5)

        # 进度条
        self.progress = ttk.Progressbar(
            self.root,
            orient="horizontal",
            length=500,
            mode="determinate"
        )
        self.progress.pack(pady=10)

        self.status_label = tk.Label(self.root, text="准备就绪", bd=1, relief="sunken", anchor="w")
        self.status_label.pack(fill="x", padx=10, pady=5)

        # 初始化选项状态
        self.toggle_resize()
        self.toggle_blur()
        self.toggle_contrast()

    def toggle_resize(self):
        state = "normal" if self.resize_var.get() else "disabled"
        self.resize_width_entry.config(state=state)
        self.resize_height_entry.config(state=state)
        self.resize_width_label.config(state=state)

    def toggle_blur(self):
        state = "normal" if self.blur_var.get() else "disabled"
        self.blur_radius_entry.config(state=state)
        self.blur_radius_label.config(state=state)

    def toggle_contrast(self):
        state = "normal" if self.contrast_var.get() else "disabled"
        self.contrast_entry.config(state=state)
        self.contrast_label.config(state=state)

    def select_input_folder(self):
        folder = filedialog.askdirectory(title="选择输入文件夹")
        if folder:
            self.input_folder = folder
            self.input_entry.delete(0, tk.END)
            self.input_entry.insert(0, folder)

    def select_output_folder(self):
        folder = filedialog.askdirectory(title="选择输出文件夹")
        if folder:
            self.output_folder = folder
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, folder)

    def update_status(self, message):
        self.status_label.config(text=message)
        self.root.update_idletasks()

    def process_image(self, img_path, output_path):
        try:
            with Image.open(img_path) as img:
                # 调整大小
                if self.resize_var.get():
                    width = int(self.resize_width_entry.get())
                    height = int(self.resize_height_entry.get())
                    img = img.resize((width, height), Image.Resampling.LANCZOS)

                # 转为灰度图
                if self.grayscale_var.get():
                    img = img.convert("L")

                # 模糊效果
                if self.blur_var.get():
                    radius = float(self.blur_radius_entry.get())
                    img = img.filter(ImageFilter.GaussianBlur(radius))

                # 调整对比度
                if self.contrast_var.get():
                    factor = float(self.contrast_entry.get())
                    enhancer = ImageEnhance.Contrast(img)
                    img = enhancer.enhance(factor)

                # 保存图片
                img.save(output_path)
                return True
        except Exception as e:
            print(f"处理图片 {img_path} 时出错: {e}")
            return False

    def start_processing(self):
        # 验证输入
        if not self.input_folder or not os.path.isdir(self.input_folder):
            messagebox.showerror("错误", "请选择有效的输入文件夹")
            return

        if not self.output_folder:
            messagebox.showerror("错误", "请选择输出文件夹")
            return

        if not os.path.exists(self.output_folder):
            os.makedirs(self.output_folder)

        # 获取图片文件列表
        image_files = [
            f for f in os.listdir(self.input_folder)
            if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))
        ]

        if not image_files:
            messagebox.showwarning("警告", "输入文件夹中没有找到图片文件")
            return

        # 设置进度条
        self.progress["maximum"] = len(image_files)
        self.progress["value"] = 0

        # 开始处理
        processed = 0
        for i, filename in enumerate(image_files, 1):
            input_path = os.path.join(self.input_folder, filename)
            output_path = os.path.join(self.output_folder, filename)

            self.update_status(f"正在处理: {filename} ({i}/{len(image_files)})")

            if self.process_image(input_path, output_path):
                processed += 1

            self.progress["value"] = i
            self.root.update_idletasks()

        # 处理完成
        self.update_status(f"处理完成! 成功处理 {processed}/{len(image_files)} 张图片")
        messagebox.showinfo("完成", f"批量处理完成!\n成功处理 {processed} 张图片")


if __name__ == "__main__":
    root = tk.Tk()
    app = BatchImageProcessor(root)
    root.mainloop()
相关推荐
寒士obj12 分钟前
类加载的过程
java·开发语言
无名之逆15 分钟前
大三自学笔记:探索Hyperlane框架的心路历程
java·开发语言·前端·spring boot·后端·rust·编程
站大爷IP17 分钟前
当Python遇上多线程:ThreadPoolExecutor的实用指南
python
站大爷IP24 分钟前
Python文件操作的“保险箱”:with语句深度实战指南
python
探模之翼25 分钟前
高效管理Python环境:Miniforge、pyenv和Poetry深度对比与应用
python
hweiyu0037 分钟前
tomcat指定使用的jdk版本
java·开发语言·tomcat
梦境虽美,却不长43 分钟前
C语言 学习 宏命令(预处理) 2025年6月9日14:41:39
c语言·开发语言·学习
橘子夏与单车少年k1 小时前
疏锦行Python打卡 DAY 27 函数专题2:装饰器
开发语言·python
Mikhail_G1 小时前
数据分析入门初解
大数据·运维·开发语言·python·数据分析
CodeDevMaster1 小时前
Python数据可视化:Seaborn入门与实践
python·数据可视化