返回列表 发布新帖

修改图片分辨率的工具Python源码

374 0
小K网牛逼 发表于 2 小时前 | 查看全部 阅读模式 <

马上注册,结交更多好友,享用更多功能,让你轻松玩转小K网。

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

×
因为工作需要,要改各种尺寸的图片,用 ps 修改之后,发现与我修改的还是不太一样,于是就有了这个代码,可以写好尺寸一键修改,并且可以导入多张图片
款式就是这几样的:

修改图片分辨率的工具

修改图片分辨率的工具Python源码

  1. import tkinter as tk
  2. from tkinter import ttk, filedialog, messagebox
  3. from PIL import Image
  4. import os
  5. class ImageResizerApp:
  6.     def __init__(self, root):
  7.         self.root = root
  8.         self.root.title("图片分辨率修改工具")
  9.         self.root.geometry("800x650")
  10.         self.root.configure(bg="#f0f0f0")
  11.         self.image_paths = []
  12.         self.target_width = tk.IntVar(value=800)
  13.         self.target_height = tk.IntVar(value=600)
  14.         self.keep_aspect_ratio = tk.BooleanVar(value=True)
  15.         self.output_path = ""  
  16.         self.setup_ui()
  17.     def setup_ui(self):
  18.         title_label = tk.Label(
  19.             self.root,
  20.             text="图片分辨率修改工具",
  21.             font=("Arial", 18, "bold"),
  22.             bg="#f0f0f0",
  23.             fg="#333"
  24.         )
  25.         title_label.pack(pady=15)
  26.         main_frame = tk.Frame(self.root, bg="#f0f0f0")
  27.         main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
  28.         control_frame = tk.LabelFrame(
  29.             main_frame,
  30.             text="控制面板",
  31.             font=("Arial", 12),
  32.             bg="#f0f0f0",
  33.             fg="#333",
  34.             padx=10,
  35.             pady=10
  36.         )
  37.         control_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
  38.         resolution_frame = tk.LabelFrame(
  39.             control_frame,
  40.             text="分辨率设置",
  41.             font=("Arial", 10),
  42.             bg="#f0f0f0",
  43.             fg="#333"
  44.         )
  45.         resolution_frame.pack(fill=tk.X, pady=(0, 15))
  46.         width_frame = tk.Frame(resolution_frame, bg="#f0f0f0")
  47.         width_frame.pack(fill=tk.X, pady=5)
  48.         tk.Label(width_frame, text="宽度:", font=("Arial", 10), bg="#f0f0f0").pack(side=tk.LEFT)
  49.         width_entry = tk.Entry(
  50.             width_frame,
  51.             textvariable=self.target_width,
  52.             font=("Arial", 10),
  53.             width=10
  54.         )
  55.         width_entry.pack(side=tk.RIGHT)
  56.         height_frame = tk.Frame(resolution_frame, bg="#f0f0f0")
  57.         height_frame.pack(fill=tk.X, pady=5)
  58.         tk.Label(height_frame, text="高度:", font=("Arial", 10), bg="#f0f0f0").pack(side=tk.LEFT)
  59.         height_entry = tk.Entry(
  60.             height_frame,
  61.             textvariable=self.target_height,
  62.             font=("Arial", 10),
  63.             width=10
  64.         )
  65.         height_entry.pack(side=tk.RIGHT)
  66.         aspect_check = tk.Checkbutton(
  67.             resolution_frame,
  68.             text="保持原始宽高比",
  69.             variable=self.keep_aspect_ratio,
  70.             font=("Arial", 10),
  71.             bg="#f0f0f0"
  72.         )
  73.         aspect_check.pack(pady=5)
  74.         io_frame = tk.LabelFrame(
  75.             control_frame,
  76.             text="导入导出设置",
  77.             font=("Arial", 10),
  78.             bg="#f0f0f0",
  79.             fg="#333"
  80.         )
  81.         io_frame.pack(fill=tk.X, pady=10)
  82.         
  83.         tk.Label(io_frame, text="导入图片:", font=("Arial", 10), bg="#f0f0f0").pack(anchor=tk.W, pady=(0, 5))
  84.         self.import_path_var = tk.StringVar(value="未选择")
  85.         import_path_label = tk.Label(
  86.             io_frame,
  87.             textvariable=self.import_path_var,
  88.             font=("Arial", 9),
  89.             bg="#ffffff",
  90.             relief=tk.SUNKEN,
  91.             anchor=tk.W
  92.         )
  93.         import_path_label.pack(fill=tk.X, pady=(0, 5))
  94.         
  95.         import_btn = tk.Button(
  96.             io_frame,
  97.             text="导入图片",
  98.             command=self.import_images,
  99.             bg="#4CAF50",
  100.             fg="white",
  101.             font=("Arial", 10, "bold"),
  102.             relief=tk.FLAT,
  103.             padx=10,
  104.             pady=5
  105.         )
  106.         import_btn.pack(fill=tk.X, pady=5)
  107.         tk.Label(io_frame, text="输出路径:", font=("Arial", 10), bg="#f0f0f0").pack(anchor=tk.W, pady=(0, 5))
  108.         self.output_path_var = tk.StringVar(value="未选择")
  109.         output_path_label = tk.Label(
  110.             io_frame,
  111.             textvariable=self.output_path_var,
  112.             font=("Arial", 9),
  113.             bg="#ffffff",
  114.             relief=tk.SUNKEN,
  115.             anchor=tk.W
  116.         )
  117.         output_path_label.pack(fill=tk.X, pady=(0, 5))
  118.         
  119.         select_output_btn = tk.Button(
  120.             io_frame,
  121.             text="选择输出路径",
  122.             command=self.select_output_path,
  123.             bg="#9C27B0",
  124.             fg="white",
  125.             font=("Arial", 10, "bold"),
  126.             relief=tk.FLAT,
  127.             padx=10,
  128.             pady=3
  129.         )
  130.         select_output_btn.pack(fill=tk.X)
  131.         button_frame = tk.Frame(control_frame, bg="#f0f0f0")
  132.         button_frame.pack(fill=tk.X, pady=10)
  133.         start_btn = tk.Button(
  134.             button_frame,
  135.             text="开始处理",
  136.             command=self.start_processing,
  137.             bg="#2196F3",
  138.             fg="white",
  139.             font=("Arial", 10, "bold"),
  140.             relief=tk.FLAT,
  141.             padx=10,
  142.             pady=5
  143.         )
  144.         start_btn.pack(fill=tk.X, pady=5)
  145.         reset_btn = tk.Button(
  146.             button_frame,
  147.             text="重置",
  148.             command=self.reset,
  149.             bg="#FF9800",
  150.             fg="white",
  151.             font=("Arial", 10, "bold"),
  152.             relief=tk.FLAT,
  153.             padx=10,
  154.             pady=5
  155.         )
  156.         reset_btn.pack(fill=tk.X, pady=5)
  157.         exit_btn = tk.Button(
  158.             button_frame,
  159.             text="退出",
  160.             command=self.root.quit,
  161.             bg="#f44336",
  162.             fg="white",
  163.             font=("Arial", 10, "bold"),
  164.             relief=tk.FLAT,
  165.             padx=10,
  166.             pady=5
  167.         )
  168.         exit_btn.pack(fill=tk.X, pady=5)
  169.         list_frame = tk.LabelFrame(
  170.             main_frame,
  171.             text="图片列表",
  172.             font=("Arial", 12),
  173.             bg="#f0f0f0",
  174.             fg="#333",
  175.             padx=10,
  176.             pady=10
  177.         )
  178.         list_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)
  179.         columns = ('filename', 'original_size', 'format')
  180.         self.tree = ttk.Treeview(list_frame, columns=columns, show='headings', height=5)  
  181.         self.tree.heading('filename', text='文件名')
  182.         self.tree.heading('original_size', text='原始尺寸')
  183.         self.tree.heading('format', text='格式')
  184.         self.tree.column('filename', width=200)
  185.         self.tree.column('original_size', width=100)
  186.         self.tree.column('format', width=80)
  187.         scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.tree.yview)
  188.         self.tree.configure(yscrollcommand=scrollbar.set)
  189.         
  190.         self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
  191.         scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  192.         
  193.     def import_images(self):
  194.         supported_formats = [
  195.             ("All Supported Images", "*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff;*.webp;*.ico"),
  196.             ("JPEG", "*.jpg;*.jpeg"),
  197.             ("PNG", "*.png"),
  198.             ("BMP", "*.bmp"),
  199.             ("GIF", "*.gif"),
  200.             ("TIFF", "*.tiff"),
  201.             ("WEBP", "*.webp"),
  202.             ("All Files", "*.*")
  203.         ]
  204.         
  205.         filenames = filedialog.askopenfilenames(
  206.             title="选择图片文件",
  207.             filetypes=supported_formats
  208.         )
  209.         
  210.         if filenames:
  211.             for filename in filenames:
  212.                 if filename not in self.image_paths:
  213.                     self.image_paths.append(filename)
  214.             if len(filenames) > 1:
  215.                 directories = set(os.path.dirname(path) for path in filenames)
  216.                 if len(directories) == 1:
  217.                     common_dir = list(directories)[0]
  218.                     display_text = f"来自同目录: {os.path.basename(common_dir)} ({len(filenames)}张)"
  219.                 else:
  220.                     display_text = f"多目录导入 ({len(filenames)}张)"
  221.                 self.import_path_var.set(display_text)
  222.             elif len(filenames) == 1:
  223.                 self.import_path_var.set(os.path.dirname(filenames[0]))
  224.             else:
  225.                 self.import_path_var.set("未选择")
  226.             
  227.             self.refresh_image_list()
  228.     def refresh_image_list(self):
  229.         for item in self.tree.get_children():
  230.             self.tree.delete(item)
  231.         
  232.         for path in self.image_paths:
  233.             try:
  234.                 img = Image.open(path)
  235.                 size_str = f"{img.width}x{img.height}"
  236.                 format_str = img.format or "Unknown"
  237.                 filename = os.path.basename(path)
  238.                
  239.                 self.tree.insert('', tk.END, values=(filename, size_str, format_str))
  240.             except Exception as e:
  241.                 print(f"无法读取图片 {path}: {e}")
  242.     def start_processing(self):
  243.         if not self.image_paths:
  244.             messagebox.showwarning("警告", "请先导入图片!")
  245.             return
  246.         
  247.         if not self.output_path:
  248.             self.output_path = filedialog.askdirectory(title="选择输出目录")
  249.             if not self.output_path:
  250.                 return
  251.             self.output_path_var.set(self.output_path)
  252.         
  253.         target_w = self.target_width.get()
  254.         target_h = self.target_height.get()
  255.         
  256.         if target_w <= 0 or target_h <= 0:
  257.             messagebox.showerror("错误", "请输入有效的分辨率值!")
  258.             return
  259.         
  260.         success_count = 0
  261.         error_count = 0
  262.         
  263.         for img_path in self.image_paths:
  264.             try:
  265.                 with Image.open(img_path) as img:
  266.                     original_size = img.size
  267.                     if self.keep_aspect_ratio.get():
  268.                         original_ratio = original_size[0] / original_size[1]
  269.                         target_ratio = target_w / target_h
  270.                         
  271.                         if original_ratio > target_ratio:
  272.                             new_width = target_w
  273.                             new_height = int(target_w / original_ratio)
  274.                         else:
  275.                             new_height = target_h
  276.                             new_width = int(target_h * original_ratio)
  277.                         
  278.                         resized_img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
  279.                     else:
  280.                         resized_img = img.resize((target_w, target_h), Image.Resampling.LANCZOS)
  281.                     
  282.                     base_name = os.path.splitext(os.path.basename(img_path))[0]
  283.                     extension = os.path.splitext(img_path)[1]
  284.                     output_path = os.path.join(self.output_path, f"{base_name}{extension}")
  285.                     
  286.                     counter = 1
  287.                     original_output_path = output_path
  288.                     while os.path.exists(output_path):
  289.                         name_part = os.path.splitext(original_output_path)[0]
  290.                         ext_part = os.path.splitext(original_output_path)[1]
  291.                         output_path = f"{name_part}_resized_{counter}{ext_part}"
  292.                         counter += 1
  293.                     
  294.                     resized_img.save(output_path, optimize=True, quality=95)
  295.                     success_count += 1
  296.                     
  297.             except Exception as e:
  298.                 print(f"处理图片失败 {img_path}: {e}")
  299.                 error_count += 1
  300.         
  301.         messagebox.showinfo(
  302.             "处理完成",
  303.             f"成功处理 {success_count} 张图片\n{error_count} 张图片处理失败"
  304.         )
  305.     def reset(self):
  306.         self.image_paths.clear()
  307.         self.target_width.set(800)
  308.         self.target_height.set(600)
  309.         self.keep_aspect_ratio.set(True)
  310.         self.output_path = ""
  311.         self.output_path_var.set("未选择")
  312.         self.refresh_image_list()
  313.    
  314.     def select_output_path(self):
  315.         """选择输出路径"""
  316.         selected_path = filedialog.askdirectory(title="选择输出目录")
  317.         if selected_path:
  318.             self.output_path = selected_path
  319.             self.output_path_var.set(selected_path)
  320. if __name__ == "__main__":
  321.     root = tk.Tk()
  322.     app = ImageResizerApp(root)
  323.     root.mainloop()
复制代码


回复

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

您需要 登录 后才可以回复,轻松玩转社区,没有帐号?立即注册
快速回复
关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表