基于Python实现图片格式批量转换器

Written by

in

文章目录
  • Python 3.6+ Pillow库 (PIL的fork版本) 安装Pillow库: pip install pillow
  • 支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等) 批量处理指定文件夹中的所有图片 可选择保留原始图片或仅保留转换后的图片 支持调整图片质量和大小 简单的命令行界面和图形用户界面(GUI)两种使用方式
  • #!/usr/bin/env python # -*- coding: utf-8 -*- “”” 图片格式批量转换器 功能: 批量将图片从一种格式转换为另一种格式,支持调整大小和质量 作者: Python开发者 “”” from PIL import Image import os import sys import argparse from pathlib import Path import tkinter as tk from tkinter import filedialog, messagebox, ttk def convert_image(input_path, output_path, format, quality=95, resize=None): “”” 转换单个图片的格式 参数: input_path – 输入图片路径 output_path – 输出图片路径 format – 目标格式 (如 ‘JPEG’, ‘PNG’) quality – 图片质量 (1-100, 仅对JPEG格式有效) resize – 调整大小的元组 (width, height) 或 None 返回: bool – 转换是否成功 “”” try: # 打开图片 img = Image.open(input_path) # 如果是RGBA模式且转换为JPEG,需要转换为RGB模式 if img.mode == ‘RGBA’ and format.upper() == ‘JPEG’: img = img.convert(‘RGB’) # 调整大小 if resize: img = img.resize(resize, Image.LANCZOS) # 保存转换后的图片 if format.upper() == ‘JPEG’: img.save(output_path, format=format, quality=quality) else: img.save(output_path, format=format) return True except Exception as e: print(f”转换图片 {input_path} 时出错: {e}”) return False def batch_convert(input_dir, output_dir, target_format, quality=95, resize=None, recursive=False, keep_original=True): “”” 批量转换指定目录中的图片 参数: input_dir – 输入目录 output_dir – 输出目录 target_format – 目标格式 quality – 图片质量 resize – 调整大小的元组 recursive – 是否递归处理子目录 keep_original – 是否保留原始图片 返回: tuple – (成功数量, 失败数量) “”” # 支持的图片格式 supported_formats = [‘.jpg’, ‘.jpeg’, ‘.png’, ‘.bmp’, ‘.gif’, ‘.tiff’] # 创建输出目录 os.makedirs(output_dir, exist_ok=True) success_count = 0 failed_count = 0 # 遍历目录 for root, dirs, files in os.walk(input_dir): # 如果不递归处理子目录且不是根目录,则跳过 if not recursive and root != input_dir: continue # 创建对应的输出子目录 rel_path = os.path.relpath(root, input_dir) if rel_path != ‘.’: current_output_dir = os.path.join(output_dir, rel_path) os.makedirs(current_output_dir, exist_ok=True) else: current_output_dir = output_dir # 处理文件 for file in files: # 检查文件扩展名 ext = os.path.splitext(file)[1].lower() if ext not in supported_formats: continue # 构建输入和输出路径 input_path = os.path.join(root, file) output_filename = os.path.splitext(file)[0] + ‘.’ + target_format.lower() output_path = os.path.join(current_output_dir, output_filename) # 转换图片 if convert_image(input_path, output_path, target_format, quality, resize): success_count += 1 # 如果不保留原始图片且不是在原目录操作,则删除原始图片 if not keep_original and input_dir != output_dir: try: os.remove(input_path) except: pass else: failed_count += 1 return (success_count, failed_count) def setup_cli(): “””设置命令行参数解析器””” parser = argparse.ArgumentParser(description=’批量转换图片格式’) parser.add_argument(‘input’, help=’输入目录或文件’) parser.add_argument(‘output’, help=’输出目录’) parser.add_argument(‘format’, help=’目标格式 (如: jpg, png, bmp)’) parser.add_argument(‘-q’, ‘–quality’, type=int, default=95, help=’图片质量 (1-100, 默认: 95)’) parser.add_argument(‘-r’, ‘–recursive’, action=’store_true’, help=’递归处理子目录’) parser.add_argument(‘-k’, ‘–keep’, action=’store_true’, help=’保留原始图片’) parser.add_argument(‘–resize’, nargs=2, type=int, metavar=(‘WIDTH’, ‘HEIGHT’), help=’调整图片大小’) return parser.parse_args() class ImageConverterGUI: def __init__(self, root): self.root = root self.root.title(“图片格式批量转换器”) self.root.geometry(“600×450″) self.root.resizable(True, True) # 创建主框架 main_frame = ttk.Frame(root, padding=”10″) main_frame.pack(fill=tk.BOTH, expand=True) # 输入目录 ttk.Label(main_frame, text=”输入目录:”).grid(column=0, row=0, sticky=tk.W, pady=5) self.input_dir = tk.StringVar() ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5) ttk.Button(main_frame, text=”浏览…”, command=self.browse_input).grid(column=2, row=0, padx=5, pady=5) # 输出目录 ttk.Label(main_frame, text=”输出目录:”).grid(column=0, row=1, sticky=tk.W, pady=5) self.output_dir = tk.StringVar() ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5) ttk.Button(main_frame, text=”浏览…”, command=self.browse_output).grid(column=2, row=1, padx=5, pady=5) # 目标格式 ttk.Label(main_frame, text=”目标格式:”).grid(column=0, row=2, sticky=tk.W, pady=5) self.format_var = tk.StringVar(value=”JPEG”) formats = [“JPEG”, “PNG”, “BMP”, “GIF”, “TIFF”] ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2, sticky=tk.W, pady=5) # 图片质量 ttk.Label(main_frame, text=”图片质量:”).grid(column=0, row=3, sticky=tk.W, pady=5) self.quality_var = tk.IntVar(value=95) quality_frame = ttk.Frame(main_frame) quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5) ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack( side=tk.LEFT) ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5) # 调整大小 ttk.Label(main_frame, text=”调整大小:”).grid(column=0, row=4, sticky=tk.W, pady=5) resize_frame = ttk.Frame(main_frame) resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5) self.resize_enabled = tk.BooleanVar(value=False) ttk.Checkbutton(resize_frame, text=”启用”, variable=self.resize_enabled).pack(side=tk.LEFT) ttk.Label(resize_frame, text=”宽:”).pack(side=tk.LEFT, padx=(10, 0)) self.width_var = tk.IntVar(value=800) ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5)) ttk.Label(resize_frame, text=”高:”).pack(side=tk.LEFT) self.height_var = tk.IntVar(value=600) ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT) # 递归处理 self.recursive_var = tk.BooleanVar(value=False) ttk.Checkbutton(main_frame, text=”递归处理子目录”, variable=self.recursive_var).grid(column=1, row=5, sticky=tk.W, pady=5) # 保留原始图片 self.keep_original_var = tk.BooleanVar(value=True) ttk.Checkbutton(main_frame, text=”保留原始图片”, variable=self.keep_original_var).grid(column=1, row=6, sticky=tk.W, pady=5) # 转换按钮 ttk.Button(main_frame, text=”开始转换”, command=self.start_conversion).grid(column=1, row=7, pady=10) # 进度条 self.progress_var = tk.DoubleVar() ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3, sticky=(tk.W, tk.E), pady=5) # 状态标签 self.status_var = tk.StringVar(value=”就绪”) ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5) def browse_input(self): directory = filedialog.askdirectory() if directory: self.input_dir.set(directory) def browse_output(self): directory = filedialog.askdirectory() if directory: self.output_dir.set(directory) def start_conversion(self): input_dir = self.input_dir.get() output_dir = self.output_dir.get() target_format = self.format_var.get() quality = self.quality_var.get() recursive = self.recursive_var.get() keep_original = self.keep_original_var.get() # 检查输入 if not input_dir or not output_dir: messagebox.showerror(“错误”, “请指定输入和输出目录”) return # 检查调整大小参数 resize = None if self.resize_enabled.get(): try: width = self.width_var.get() height = self.height_var.get() if width <= 0 or height <= 0: raise ValueError(“宽度和高度必须大于0”) resize = (width, height) except: messagebox.showerror(“错误”, “调整大小参数无效”) return # 开始转换 self.status_var.set(“转换中…”) self.root.update() try: success, failed = batch_convert( input_dir, output_dir, target_format, quality, resize, recursive, keep_original ) self.status_var.set(f”转换完成。成功: {success}, 失败: {failed}”) messagebox.showinfo(“完成”, f”转换完成n成功: {success}n失败: {failed}”) except Exception as e: self.status_var.set(f”转换出错: {str(e)}”) messagebox.showerror(“错误”, f”转换过程中出错:n{str(e)}”) def main(): # 检查是否有命令行参数 if len(sys.argv) > 1: # 命令行模式 args = setup_cli() # 检查输入和输出目录 if not os.path.exists(args.input): print(f”错误: 输入路径 ‘{args.input}’ 不存在”) return # 调整大小参数 resize = tuple(args.resize) if args.resize else None # 开始转换 print(f”开始转换图片从 {args.input} 到 {args.output},格式: {args.format}”) success, failed = batch_convert( args.input, args.output, args.format.upper(), args.quality, resize, args.recursive, args.keep ) print(f”转换完成。成功: {success}, 失败: {failed}”) else: # GUI模式 root = tk.Tk() app = ImageConverterGUI(root) root.mainloop() if __name__ == “__main__”: main() 知识点: 命令行模式和GUI模式的切换 sys.argv: 获取命令行参数 tkinter主循环: root.mainloop()
  • 1. 图像处理基础 像素: 图像的基本单位 颜色模式: RGB, RGBA, CMYK, 灰度等 图像格式特点: JPEG: 有损压缩,不支持透明度,适合照片 PNG: 无损压缩,支持透明度,适合图标和截图 GIF: 支持动画,有限的颜色数量 BMP: 无压缩,文件较大 TIFF: 高质量,支持多页,常用于专业印刷 2. Pillow高级特性 图像增强: 亮度、对比度、锐化等调整 滤镜效果: 模糊、锐化、边缘检测等 图像合成: 图层混合、水印等 批处理: 多进程处理提高效率 3. 性能优化 使用生成器减少内存占用 多线程/多进程处理提高转换速度 缩略图生成优化
  • 批量水印添加:为图片添加文字或图片水印 图片批量裁剪:自动裁剪图片到指定比例或尺寸 批量图片优化:自动调整亮度、对比度和图片锐化 批量重命名:根据规则批量重命名图片文件 元数据处理:保留或清除EXIF信息 到此这篇关于基于Python实现图片格式批量转换器的文章就介绍到这了,更多相关Python图片格式转换内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客! 您可能感兴趣的文章: python实现批量图片格式转换 使用python将图片格式转换为ico格式的示例 Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中 Python实现图片格式转换 Python+PyQt5编写图片格式转换器 使用python创建图片格式转换器的实现步骤
  • 目录
    • 开发环境准备
    • 核心功能
    • 技术要点
      • 1. Pillow库基础
      • 2. 文件系统操作
      • 3. 用户界面
    • 代码实现与解析
      • 1. 导入必要的库
      • 2. 图片格式转换核心函数
      • 3. 批量转换功能
      • 4. 命令行界面
      • 5. 图形用户界面
      • 6. 主函数
    • 完整代码
      • 使用方法
        • 命令行方式
        • GUI方式
      • 进阶知识点
        • 可扩展功能

          Python 3.6+

          Pillow库 (PIL的fork版本)

          安装Pillow库:

          pip install pillow
          

          支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等)

          批量处理指定文件夹中的所有图片

          可选择保留原始图片或仅保留转换后的图片

          支持调整图片质量和大小

          简单的命令行界面和图形用户界面(GUI)两种使用方式

          Pillow是Python图像处理库(PIL)的一个分支,提供了丰富的图像处理功能。主要用到的模块:

          • Image: 图像对象的创建、读取和保存
          • ImageOps: 图像操作,如调整大小、翻转等
          • ImageEnhance: 图像增强,如亮度、对比度调整

          使用os和pathlib模块处理文件路径

          递归遍历目录

          文件类型判断

          命令行参数解析

          简单GUI界面构建(使用tkinter)

          from PIL import Image
          import os
          import sys
          import argparse
          from pathlib import Path
          import tkinter as tk
          from tkinter import filedialog, messagebox, ttk
          

          知识点:

          PIL.Image: Pillow的核心模块,用于图像处理

          os和pathlib: 文件系统操作

          argparse: 命令行参数解析

          tkinter: Python标准GUI库

          def convert_image(input_path, output_path, format, quality=95, resize=None):
              """
              转换单个图片的格式
              
              参数:
              input_path - 输入图片路径
              output_path - 输出图片路径
              format - 目标格式 (如 'JPEG', 'PNG')
              quality - 图片质量 (1-100, 仅对JPEG格式有效)
              resize - 调整大小的元组 (width, height) 或 None
              
              返回:
              bool - 转换是否成功
              """
              try:
                  # 打开图片
                  img = Image.open(input_path)
                  
                  # 如果是RGBA模式且转换为JPEG,需要转换为RGB模式
                  if img.mode == 'RGBA' and format.upper() == 'JPEG':
                      img = img.convert('RGB')
                  
                  # 调整大小
                  if resize:
                      img = img.resize(resize, Image.LANCZOS)
                  
                  # 保存转换后的图片
                  if format.upper() == 'JPEG':
                      img.save(output_path, format=format, quality=quality)
                  else:
                      img.save(output_path, format=format)
                  
                  return True
              except Exception as e:
                  print(f"转换图片 {input_path} 时出错: {e}")
                  return False

          知识点:

          Image.open(): 打开图片文件

          图像模式转换: RGBA转RGB(JPEG不支持透明通道)

          Image.LANCZOS: 高质量的图像缩放算法

          异常处理: 捕获并处理可能的错误

          def batch_convert(input_dir, output_dir, target_format, quality=95, 
                           resize=None, recursive=False, keep_original=True):
              """
              批量转换指定目录中的图片
              
              参数:
              input_dir - 输入目录
              output_dir - 输出目录
              target_format - 目标格式
              quality - 图片质量
              resize - 调整大小的元组
              recursive - 是否递归处理子目录
              keep_original - 是否保留原始图片
              
              返回:
              tuple - (成功数量, 失败数量)
              """
              # 支持的图片格式
              supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']
              
              # 创建输出目录
              os.makedirs(output_dir, exist_ok=True)
              
              success_count = 0
              failed_count = 0
              
              # 遍历目录
              for root, dirs, files in os.walk(input_dir):
                  # 如果不递归处理子目录且不是根目录,则跳过
                  if not recursive and root != input_dir:
                      continue
                      
                  # 创建对应的输出子目录
                  rel_path = os.path.relpath(root, input_dir)
                  if rel_path != '.':
                      current_output_dir = os.path.join(output_dir, rel_path)
                      os.makedirs(current_output_dir, exist_ok=True)
                  else:
                      current_output_dir = output_dir
                  
                  # 处理文件
                  for file in files:
                      # 检查文件扩展名
                      ext = os.path.splitext(file)[1].lower()
                      if ext not in supported_formats:
                          continue
                          
                      # 构建输入和输出路径
                      input_path = os.path.join(root, file)
                      output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()
                      output_path = os.path.join(current_output_dir, output_filename)
                      
                      # 转换图片
                      if convert_image(input_path, output_path, target_format, quality, resize):
                          success_count += 1
                          # 如果不保留原始图片且不是在原目录操作,则删除原始图片
                          if not keep_original and input_dir != output_dir:
                              try:
                                  os.remove(input_path)
                              except:
                                  pass
                      else:
                          failed_count += 1
              
              return (success_count, failed_count)

          知识点:

          os.walk(): 递归遍历目录

          os.path.relpath(): 获取相对路径

          os.makedirs(): 创建多级目录

          文件扩展名处理: 使用os.path.splitext()分离文件名和扩展名

          def setup_cli():
              """设置命令行参数解析器"""
              parser = argparse.ArgumentParser(description='批量转换图片格式')
              
              parser.add_argument('input', help='输入目录或文件')
              parser.add_argument('output', help='输出目录')
              parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')
              parser.add_argument('-q', '--quality', type=int, default=95, 
                                  help='图片质量 (1-100, 默认: 95)')
              parser.add_argument('-r', '--recursive', action='store_true', 
                                  help='递归处理子目录')
              parser.add_argument('-k', '--keep', action='store_true', 
                                  help='保留原始图片')
              parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),
                                  help='调整图片大小')
              
              return parser.parse_args()

          知识点:

          argparse: 命令行参数解析

          参数类型: 位置参数、可选参数、标志参数

          参数类型转换: 使用type=int将字符串转换为整数

          class ImageConverterGUI:
              def __init__(self, root):
                  self.root = root
                  self.root.title("图片格式批量转换器")
                  self.root.geometry("600x450")
                  self.root.resizable(True, True)
                  
                  # 创建主框架
                  main_frame = ttk.Frame(root, padding="10")
                  main_frame.pack(fill=tk.BOTH, expand=True)
                  
                  # 输入目录
                  ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)
                  self.input_dir = tk.StringVar()
                  ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)
                  ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)
                  
                  # 输出目录
                  ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)
                  self.output_dir = tk.StringVar()
                  ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)
                  ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)
                  
                  # 目标格式
                  ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)
                  self.format_var = tk.StringVar(value="JPEG")
                  formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]
                  ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2, sticky=tk.W, pady=5)
                  
                  # 图片质量
                  ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)
                  self.quality_var = tk.IntVar(value=95)
                  quality_frame = ttk.Frame(main_frame)
                  quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)
                  ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(side=tk.LEFT)
                  ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)
                  
                  # 调整大小
                  ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)
                  resize_frame = ttk.Frame(main_frame)
                  resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)
                  self.resize_enabled = tk.BooleanVar(value=False)
                  ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)
                  ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))
                  self.width_var = tk.IntVar(value=800)
                  ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))
                  ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)
                  self.height_var = tk.IntVar(value=600)
                  ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)
                  
                  # 递归处理
                  self.recursive_var = tk.BooleanVar(value=False)
                  ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5, sticky=tk.W, pady=5)
                  
                  # 保留原始图片
                  self.keep_original_var = tk.BooleanVar(value=True)
                  ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6, sticky=tk.W, pady=5)
                  
                  # 转换按钮
                  ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)
                  
                  # 进度条
                  self.progress_var = tk.DoubleVar()
                  ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3, sticky=(tk.W, tk.E), pady=5)
                  
                  # 状态标签
                  self.status_var = tk.StringVar(value="就绪")
                  ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)
                  
              def browse_input(self):
                  directory = filedialog.askdirectory()
                  if directory:
                      self.input_dir.set(directory)
                      
              def browse_output(self):
                  directory = filedialog.askdirectory()
                  if directory:
                      self.output_dir.set(directory)
              
              def start_conversion(self):
                  input_dir = self.input_dir.get()
                  output_dir = self.output_dir.get()
                  target_format = self.format_var.get()
                  quality = self.quality_var.get()
                  recursive = self.recursive_var.get()
                  keep_original = self.keep_original_var.get()
                  
                  # 检查输入
                  if not input_dir or not output_dir:
                      messagebox.showerror("错误", "请指定输入和输出目录")
                      return
                      
                  # 检查调整大小参数
                  resize = None
                  if self.resize_enabled.get():
                      try:
                          width = self.width_var.get()
                          height = self.height_var.get()
                          if width <= 0 or height <= 0:
                              raise ValueError("宽度和高度必须大于0")
                          resize = (width, height)
                      except:
                          messagebox.showerror("错误", "调整大小参数无效")
                          return
                  
                  # 开始转换
                  self.status_var.set("转换中...")
                  self.root.update()
                  
                  try:
                      success, failed = batch_convert(
                          input_dir, output_dir, target_format, quality,
                          resize, recursive, keep_original
                      )
                      
                      self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")
                      messagebox.showinfo("完成", f"转换完成n成功: {success}n失败: {failed}")
                  except Exception as e:
                      self.status_var.set(f"转换出错: {str(e)}")
                      messagebox.showerror("错误", f"转换过程中出错:n{str(e)}")

          知识点:

          tkinter: Python标准GUI库

          布局管理: 使用grid布局

          控件使用: 标签、输入框、按钮、复选框、组合框、进度条等

          事件处理: 按钮点击事件

          文件对话框: 使用filedialog选择目录

          def main():
              # 检查是否有命令行参数
              if len(sys.argv) > 1:
                  # 命令行模式
                  args = setup_cli()
                  
                  # 检查输入和输出目录
                  if not os.path.exists(args.input):
                      print(f"错误: 输入路径 '{args.input}' 不存在")
                      return
                      
                  # 调整大小参数
                  resize = tuple(args.resize) if args.resize else None
                  
                  # 开始转换
                  print(f"开始转换图片从 {args.input} 到 {args.output},格式: {args.format}")
                  success, failed = batch_convert(
                      args.input, args.output, args.format.upper(),
                      args.quality, resize, args.recursive, args.keep
                  )
                  
                  print(f"转换完成。成功: {success}, 失败: {failed}")
              else:
                  # GUI模式
                  root = tk.Tk()
                  app = ImageConverterGUI(root)
                  root.mainloop()
          
          ​​​​​​​if __name__ == "__main__":
              main()

          #!/usr/bin/env python
          # -*- coding: utf-8 -*-
          
          """
          图片格式批量转换器
          功能: 批量将图片从一种格式转换为另一种格式,支持调整大小和质量
          作者: Python开发者
          """
          
          from PIL import Image
          import os
          import sys
          import argparse
          from pathlib import Path
          import tkinter as tk
          from tkinter import filedialog, messagebox, ttk
          
          
          def convert_image(input_path, output_path, format, quality=95, resize=None):
              """
              转换单个图片的格式
          
              参数:
              input_path - 输入图片路径
              output_path - 输出图片路径
              format - 目标格式 (如 'JPEG', 'PNG')
              quality - 图片质量 (1-100, 仅对JPEG格式有效)
              resize - 调整大小的元组 (width, height) 或 None
          
              返回:
              bool - 转换是否成功
              """
              try:
                  # 打开图片
                  img = Image.open(input_path)
          
                  # 如果是RGBA模式且转换为JPEG,需要转换为RGB模式
                  if img.mode == 'RGBA' and format.upper() == 'JPEG':
                      img = img.convert('RGB')
          
                  # 调整大小
                  if resize:
                      img = img.resize(resize, Image.LANCZOS)
          
                  # 保存转换后的图片
                  if format.upper() == 'JPEG':
                      img.save(output_path, format=format, quality=quality)
                  else:
                      img.save(output_path, format=format)
          
                  return True
              except Exception as e:
                  print(f"转换图片 {input_path} 时出错: {e}")
                  return False
          
          
          def batch_convert(input_dir, output_dir, target_format, quality=95,
                            resize=None, recursive=False, keep_original=True):
              """
              批量转换指定目录中的图片
          
              参数:
              input_dir - 输入目录
              output_dir - 输出目录
              target_format - 目标格式
              quality - 图片质量
              resize - 调整大小的元组
              recursive - 是否递归处理子目录
              keep_original - 是否保留原始图片
          
              返回:
              tuple - (成功数量, 失败数量)
              """
              # 支持的图片格式
              supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']
          
              # 创建输出目录
              os.makedirs(output_dir, exist_ok=True)
          
              success_count = 0
              failed_count = 0
          
              # 遍历目录
              for root, dirs, files in os.walk(input_dir):
                  # 如果不递归处理子目录且不是根目录,则跳过
                  if not recursive and root != input_dir:
                      continue
          
                  # 创建对应的输出子目录
                  rel_path = os.path.relpath(root, input_dir)
                  if rel_path != '.':
                      current_output_dir = os.path.join(output_dir, rel_path)
                      os.makedirs(current_output_dir, exist_ok=True)
                  else:
                      current_output_dir = output_dir
          
                  # 处理文件
                  for file in files:
                      # 检查文件扩展名
                      ext = os.path.splitext(file)[1].lower()
                      if ext not in supported_formats:
                          continue
          
                      # 构建输入和输出路径
                      input_path = os.path.join(root, file)
                      output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()
                      output_path = os.path.join(current_output_dir, output_filename)
          
                      # 转换图片
                      if convert_image(input_path, output_path, target_format, quality, resize):
                          success_count += 1
                          # 如果不保留原始图片且不是在原目录操作,则删除原始图片
                          if not keep_original and input_dir != output_dir:
                              try:
                                  os.remove(input_path)
                              except:
                                  pass
                      else:
                          failed_count += 1
          
              return (success_count, failed_count)
          
          
          def setup_cli():
              """设置命令行参数解析器"""
              parser = argparse.ArgumentParser(description='批量转换图片格式')
          
              parser.add_argument('input', help='输入目录或文件')
              parser.add_argument('output', help='输出目录')
              parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')
              parser.add_argument('-q', '--quality', type=int, default=95,
                                  help='图片质量 (1-100, 默认: 95)')
              parser.add_argument('-r', '--recursive', action='store_true',
                                  help='递归处理子目录')
              parser.add_argument('-k', '--keep', action='store_true',
                                  help='保留原始图片')
              parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),
                                  help='调整图片大小')
          
              return parser.parse_args()
          
          
          class ImageConverterGUI:
              def __init__(self, root):
                  self.root = root
                  self.root.title("图片格式批量转换器")
                  self.root.geometry("600x450")
                  self.root.resizable(True, True)
          
                  # 创建主框架
                  main_frame = ttk.Frame(root, padding="10")
                  main_frame.pack(fill=tk.BOTH, expand=True)
          
                  # 输入目录
                  ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)
                  self.input_dir = tk.StringVar()
                  ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)
                  ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)
          
                  # 输出目录
                  ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)
                  self.output_dir = tk.StringVar()
                  ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)
                  ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)
          
                  # 目标格式
                  ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)
                  self.format_var = tk.StringVar(value="JPEG")
                  formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]
                  ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2,
                                                                                                        sticky=tk.W, pady=5)
          
                  # 图片质量
                  ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)
                  self.quality_var = tk.IntVar(value=95)
                  quality_frame = ttk.Frame(main_frame)
                  quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)
                  ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(
                      side=tk.LEFT)
                  ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)
          
                  # 调整大小
                  ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)
                  resize_frame = ttk.Frame(main_frame)
                  resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)
                  self.resize_enabled = tk.BooleanVar(value=False)
                  ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)
                  ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))
                  self.width_var = tk.IntVar(value=800)
                  ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))
                  ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)
                  self.height_var = tk.IntVar(value=600)
                  ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)
          
                  # 递归处理
                  self.recursive_var = tk.BooleanVar(value=False)
                  ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5,
                                                                                                       sticky=tk.W, pady=5)
          
                  # 保留原始图片
                  self.keep_original_var = tk.BooleanVar(value=True)
                  ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6,
                                                                                                         sticky=tk.W, pady=5)
          
                  # 转换按钮
                  ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)
          
                  # 进度条
                  self.progress_var = tk.DoubleVar()
                  ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3,
                                                                                            sticky=(tk.W, tk.E), pady=5)
          
                  # 状态标签
                  self.status_var = tk.StringVar(value="就绪")
                  ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)
          
              def browse_input(self):
                  directory = filedialog.askdirectory()
                  if directory:
                      self.input_dir.set(directory)
          
              def browse_output(self):
                  directory = filedialog.askdirectory()
                  if directory:
                      self.output_dir.set(directory)
          
              def start_conversion(self):
                  input_dir = self.input_dir.get()
                  output_dir = self.output_dir.get()
                  target_format = self.format_var.get()
                  quality = self.quality_var.get()
                  recursive = self.recursive_var.get()
                  keep_original = self.keep_original_var.get()
          
                  # 检查输入
                  if not input_dir or not output_dir:
                      messagebox.showerror("错误", "请指定输入和输出目录")
                      return
          
                  # 检查调整大小参数
                  resize = None
                  if self.resize_enabled.get():
                      try:
                          width = self.width_var.get()
                          height = self.height_var.get()
                          if width <= 0 or height <= 0:
                              raise ValueError("宽度和高度必须大于0")
                          resize = (width, height)
                      except:
                          messagebox.showerror("错误", "调整大小参数无效")
                          return
          
                  # 开始转换
                  self.status_var.set("转换中...")
                  self.root.update()
          
                  try:
                      success, failed = batch_convert(
                          input_dir, output_dir, target_format, quality,
                          resize, recursive, keep_original
                      )
          
                      self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")
                      messagebox.showinfo("完成", f"转换完成n成功: {success}n失败: {failed}")
                  except Exception as e:
                      self.status_var.set(f"转换出错: {str(e)}")
                      messagebox.showerror("错误", f"转换过程中出错:n{str(e)}")
          
          
          def main():
              # 检查是否有命令行参数
              if len(sys.argv) > 1:
                  # 命令行模式
                  args = setup_cli()
          
                  # 检查输入和输出目录
                  if not os.path.exists(args.input):
                      print(f"错误: 输入路径 '{args.input}' 不存在")
                      return
          
                  # 调整大小参数
                  resize = tuple(args.resize) if args.resize else None
          
                  # 开始转换
                  print(f"开始转换图片从 {args.input} 到 {args.output},格式: {args.format}")
                  success, failed = batch_convert(
                      args.input, args.output, args.format.upper(),
                      args.quality, resize, args.recursive, args.keep
                  )
          
                  print(f"转换完成。成功: {success}, 失败: {failed}")
              else:
                  # GUI模式
                  root = tk.Tk()
                  app = ImageConverterGUI(root)
                  root.mainloop()
          
          
          if __name__ == "__main__":
              main()
          

          知识点:

          命令行模式和GUI模式的切换

          sys.argv: 获取命令行参数

          tkinter主循环: root.mainloop()

          # 基本用法
          python image_converter.py 输入目录 输出目录 目标格式
          
          # 示例: 将input_folder中的图片转换为PNG格式并保存到output_folder
          python image_converter.py input_folder output_folder png
          
          # 高级用法
          python image_converter.py input_folder output_folder jpg -q 85 -r --resize 800 600
          

          直接运行程序,不带任何参数:

          python image_converter.py
          

          然后在图形界面中:

          • 选择输入目录
          • 选择输出目录
          • 设置目标格式和其他选项
          • 点击"开始转换"按钮

          1. 图像处理基础

          像素: 图像的基本单位

          颜色模式: RGB, RGBA, CMYK, 灰度等

          图像格式特点:

          • JPEG: 有损压缩,不支持透明度,适合照片
          • PNG: 无损压缩,支持透明度,适合图标和截图
          • GIF: 支持动画,有限的颜色数量
          • BMP: 无压缩,文件较大
          • TIFF: 高质量,支持多页,常用于专业印刷

          2. Pillow高级特性

          • 图像增强: 亮度、对比度、锐化等调整
          • 滤镜效果: 模糊、锐化、边缘检测等
          • 图像合成: 图层混合、水印等
          • 批处理: 多进程处理提高效率

          3. 性能优化

          • 使用生成器减少内存占用
          • 多线程/多进程处理提高转换速度
          • 缩略图生成优化

          批量水印添加:为图片添加文字或图片水印

          图片批量裁剪:自动裁剪图片到指定比例或尺寸

          批量图片优化:自动调整亮度、对比度和图片锐化

          批量重命名:根据规则批量重命名图片文件

          元数据处理:保留或清除EXIF信息

          到此这篇关于基于Python实现图片格式批量转换器的文章就介绍到这了,更多相关Python图片格式转换内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!

          您可能感兴趣的文章:

          • python实现批量图片格式转换
          • 使用python将图片格式转换为ico格式的示例
          • Python 实现判断图片格式并转换,将转换的图像存到生成的文件夹中
          • Python实现图片格式转换
          • Python+PyQt5编写图片格式转换器
          • 使用python创建图片格式转换器的实现步骤

          站内搜索