Python图片格式批量转换器教程

news2025/6/2 5:44:40

📚 前言

编程基础第一期《11-30》-- 在图像处理工作中,我们经常需要将大量图片从一种格式转换为另一种格式。本教程将介绍如何使用Python的Pillow库开发一个简单但功能强大的图片格式批量转换器,帮助你高效处理图片格式转换任务。

目录

    • 📚 前言
    • 🛠️ 开发环境准备
    • 💡 核心功能
    • 🧩 技术要点
      • 1. Pillow库基础
      • 2. 文件系统操作
      • 3. 用户界面
    • 📝 代码实现与解析
      • 1. 导入必要的库
      • 2. 图片格式转换核心函数
      • 3. 批量转换功能
      • 4. 命令行界面
      • 5. 图形用户界面
      • 6. 主函数
    • 🎮 使用方法
      • 命令行方式
      • GUI方式
    • 🔍 进阶知识点
      • 1. 图像处理基础
      • 2. Pillow高级特性
      • 3. 性能优化
    • 🚀 可扩展功能
    • 📝 总结

🛠️ 开发环境准备

  • Python 3.6+
  • Pillow库 (PIL的fork版本)

安装Pillow库:

pip install pillow

💡 核心功能

  1. 支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等)
  2. 批量处理指定文件夹中的所有图片
  3. 可选择保留原始图片或仅保留转换后的图片
  4. 支持调整图片质量和大小
  5. 简单的命令行界面和图形用户界面(GUI)两种使用方式

🧩 技术要点

1. Pillow库基础

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

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

2. 文件系统操作

  • 使用ospathlib模块处理文件路径
  • 递归遍历目录
  • 文件类型判断

3. 用户界面

  • 命令行参数解析
  • 简单GUI界面构建(使用tkinter)

📝 代码实现与解析

1. 导入必要的库

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的核心模块,用于图像处理
  • ospathlib: 文件系统操作
  • argparse: 命令行参数解析
  • tkinter: Python标准GUI库

2. 图片格式转换核心函数

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: 高质量的图像缩放算法
  • 异常处理: 捕获并处理可能的错误

3. 批量转换功能

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()分离文件名和扩展名

4. 命令行界面

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将字符串转换为整数

5. 图形用户界面

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选择目录

6. 主函数

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

GUI方式

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

python image_converter.py

然后在图形界面中:

  1. 选择输入目录
  2. 选择输出目录
  3. 设置目标格式和其他选项
  4. 点击"开始转换"按钮
    在这里插入图片描述

🔍 进阶知识点

1. 图像处理基础

  • 像素: 图像的基本单位
  • 颜色模式: RGB, RGBA, CMYK, 灰度等
  • 图像格式特点:
    • JPEG: 有损压缩,不支持透明度,适合照片
    • PNG: 无损压缩,支持透明度,适合图标和截图
    • GIF: 支持动画,有限的颜色数量
    • BMP: 无压缩,文件较大
    • TIFF: 高质量,支持多页,常用于专业印刷

2. Pillow高级特性

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

3. 性能优化

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

🚀 可扩展功能

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

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

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

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

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

📝 总结

通过这个图片格式批量转换器项目,我们学习了以下Python编程知识:

  1. Pillow库的基本使用
  2. 文件系统操作
  3. 命令行参数解析
  4. GUI界面开发
  5. 批处理和异常处理
  6. 图像处理基础知识

物物而不物于物,念念而不念于念

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2393530.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从公开到私密:重新思考 Web3 的数据安全

去中心化存储是 Web3 的基石之一&#xff0c;使用户和应用能够在无需依赖中心化服务商的情况下存储数据。但自由也带来了一个重大挑战&#xff1a;数据安全。在一个无许可的世界中&#xff0c;如何确保用户文档、游戏资产或 AI 数据集等敏感内容是私密的、可控访问的&#xff0…

计算机网络常见体系结构、分层必要性、分层设计思想以及专用术语介绍

计算机网络体系结构 从本此开始&#xff0c;我们就要开始介绍有关计算机网络体系结构的知识了。内容包括&#xff1a; 常见的计算机网络体系结构 计算机网络体系结构分层的必要性 计算机网络体系结构的设计思想 举例说明及专用术语 计算机网络体系结构是计算机网络课程中…

接口自动化测试用例的编写方法

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 phpunit 接口自动化测试系列 Post接口自动化测试用例 Post方式的接口是上传接口&#xff0c;需要对接口头部进行封装&#xff0c;所以没有办法在浏览器下直接调…

基于SpringBoot的商家销售管理网站的设计与实现

湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 基于SpringBoot的商家销售管理网站的设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕…

word中表格拉不动以及插入图片有间距

1、word中表格插入图片始终有间隙&#xff0c;怎么调表格高度和宽度都消除不了间隙&#xff0c;如下所示&#xff1a; 可以在表布局—单元格边距—修改上下左右边距为0即可 2、经过上述调整后左右没有间隔了&#xff0c;但图片上下有间隔&#xff0c;直觉是行距问题&#xff0c…

【Java学习笔记】接口

接口 应用场景引出 一、接口的介绍 1. 接口的基本结构 interface 接口名{属性抽象方法 }引出关键字&#xff1a;implements 2. 子类实现接口 class a implements 接口名{}3. 接口中的属性说明&#xff1a;属性默认是public static final修饰的 &#xff08;1&#xff09;f…

代码随想录打卡|Day50 图论(拓扑排序精讲 、dijkstra(朴素版)精讲 )

图论part08 拓扑排序精讲 代码随想录讲解链接 题目链接 思路 在这个题目之中&#xff0c;个别文件的处理依赖于别的文件&#xff0c;因此&#xff0c;文件的处理顺序十分重要。我们用图来表示文件的处理顺序&#xff0c;文件s指向文件t&#xff0c;则说明如果要正确的处理文…

SI24R05国产低功耗2.4GHz+125K低频唤醒SoC人员定位/畜牧业牛羊定位/资产管理定位方案芯片

目录 SI24R05简介功能框图 主要特性开发工具方案特性 SI24R05简介 Si24R05 是一款高度集成的低功耗 SOC 芯片&#xff0c;具有低功耗、Low Pin Count、 宽电压工作范围&#xff0c;集成了 13/14/15/16 位精度的 ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、无线收发器、…

基于ELK的分布式日志实时分析与可视化系统设计

目录 一、ELK平台介绍 1.ELK概述 2.Elasticsearch 3.Logstash 4.Kibana 二、部署ES群集 1.资源清单 2.基本配置 3.安装Elasticsearch&#xff08;elk1上、elk2上、elk3上&#xff09; 4.安装logstash&#xff08;elk1上&#xff09; 5.Filebeat 6.安装Kibana&#x…

酒店管理系统设计与实现

本科毕业设计(论文) 设计(论文)题目 酒店管理系统设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 李建 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕业设计(论文)作品是本人在指导教师的指…

OpenCV---pointPolygonTest

一、基本概念与用途 pointPolygonTest 是 OpenCV 中用于判断点与多边形关系的重要函数&#xff0c;常用于&#xff1a; 目标检测&#xff1a;判断像素点是否属于检测到的轮廓区域碰撞检测&#xff1a;检测物体是否重叠图像分割&#xff1a;确定点是否在分割区域内几何分析&am…

Qt 的简单示例 -- 地址簿

这个工程里有两个窗口&#xff0c;都是QWidget派生的窗口 主窗口&#xff1a; 1. 运用了布局&#xff0c;按钮控件&#xff0c;单行编辑框&#xff0c;富文本编辑框等窗口部件&#xff1b; 2. 运用了 QMap 类&#xff1b; 3. 实现了点击按钮弹出子窗口的功能&#xff0c;这里子…

什么是DevOps的核心目标?它如何解决传统开发与运维之间的冲突?​

在当今数字化转型加速的时代&#xff0c;DevOps 已成为软件开发领域备受瞩目的明星理念。今天&#xff0c;本文将聚焦于 DevOps 的核心目标&#xff0c;并深入探讨它如何巧妙化解传统开发与运维之间的冲突&#xff0c;为大家揭开 DevOps 的神秘面纱并分享实用经验。本次介绍的与…

Android studio 查看aar源码出现/* compiled code */

如图查看aar源码时看不到具体实现&#xff0c;在排除是sdk版本导致的问题后&#xff0c;下面说解决方法 打开设置&#xff0c;找到插件 输入decompiler 搜索 这个是自带的反编译工具&#xff0c;启用就好了

用HTML5+JavaScript实现汉字转拼音工具

用HTML5JavaScript实现汉字转拼音工具 前一篇博文&#xff08;https://blog.csdn.net/cnds123/article/details/148067680&#xff09;提到&#xff0c;当需要将拼音添加到汉字上面时&#xff0c;用python实现比HTML5JavaScript实现繁琐。在这篇博文中用HTML5JavaScript实现汉…

基于Java,SpringBoot,Vue,UniAPP医院预约挂号买药就诊病例微信小程序系统设计

摘要 随着医疗信息化的不断推进以及“互联网医疗”模式的广泛普及&#xff0c;传统医院挂号流程中存在的排队时间长、资源分配不均等问题日益凸显&#xff0c;急需通过数字化手段加以解决。本研究设计并实现了一套基于Java、SpringBoot、Vue与UniAPP技术栈的医院预约挂号微信小…

ONNX模型的动态和静态量化

引言  通常我们将模型转换为onnx格式之后&#xff0c;模型的体积可能比较大&#xff0c;这样在某些场景下就无法适用。最近想在移动端部署语音识别、合成模型&#xff0c;但是目前的效果较好的模型动辄几个G&#xff0c;于是便想着将模型压缩一下。本文探索了两种压缩方法&…

如何用Python抓取Google Scholar

文章目录 [TOC](文章目录) 前言一、为什么要抓取Google Scholar&#xff1f;二、Google Scholar 抓取需要什么三、为什么代理对于稳定的抓取是必要的四、一步一步谷歌学者抓取教程4.1. 分页和循环4.2. 运行脚本 五、完整的Google Scholar抓取代码六、抓取Google Scholar的高级提…

Wireshark对usb设备进行抓包找不到USBPcap接口的解决方案

引言 近日工作需要针对usb设备进行抓包&#xff0c;但按照wireshark安装程序流程一步步走&#xff0c;即使勾选了安装USBPcap安装完成后开启wireshark依然不显示USBPcap接口&#xff0c;随设法进行解决。 最终能够正常显示USBPcap接口并能够正常使用进行抓包 解决方案&#x…

Socket 编程 UDP

目录 1. UDP网络编程 1.1 echo server 1.1.1 接口 1.1.1.1 创建套接字 1.1.1.2 绑定 1.1.1.3 bzero 1.1.1.4 htons&#xff08;主机序列转网络序列&#xff09; 1.1.1.5 inet_addr&#xff08;主机序列IP转网络序列IP&#xff09; 1.1.1.6 recvfrom&#xff08;让服务…