脚本专家 发表于 2026-8-31 14:00:01

Python脚本实现Webp PNG JPG图片批量互转与无损压缩

在网站图片优化、客户交付或系统图标上传等场景中,经常需要把图片在 WebP、PNG、JPG 之间互相转换,同时兼顾体积压缩。手动用画图工具逐张处理效率太低,用 Python 结合 Pillow 可以快速实现批量转换与压缩。

Pillow 是 Python 最常用的图像处理库,它可以把任意常见格式的图片读取为统一的 Image 对象,再按指定格式保存。转换时主要涉及有损/无损格式差异、透明通道处理和压缩质量参数。JPG 使用有损压缩且不支持透明;PNG 使用无损压缩且支持透明;WebP 是 Google 推出的网页图片格式,体积通常更小;BMP 无压缩,TIFF 支持多层,适合存档。

环境准备:
pip install Pillow

代码实现分为三个工具函数。

一、单张格式转换
convert_image(input_file, output_format='jpg', quality=85, max_size=None) 接收输入路径、目标格式、质量值和最大尺寸。打开图片后,若指定 max_size 则用 thumbnail 等比缩放;若输出格式为 jpg/jpeg/bmp 且原图是 RGBA,则先用白色背景合成,去掉透明通道;输出文件名自动替换扩展名;保存时按格式设置不同参数:jpg/jpeg 用 quality+optimize,webp 用 quality+method=6,png 用 optimize。最后打印原图与新图体积差。


import os
from pathlib import Path
from PIL import Image

SUPPORTED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.webp', '.bmp', '.tiff', '.gif'}

def convert_image(input_file, output_format='jpg', quality=85, max_size=None):
    input_path = Path(input_file)
    img = Image.open(input_path)

    if max_size:
      img.thumbnail(max_size, Image.LANCZOS)

    if output_format in ('jpg', 'jpeg', 'bmp') and img.mode == 'RGBA':
      background = Image.new('RGB', img.size, (255, 255, 255))
      background.paste(img, mask=img.split())
      img = background

    output_file = input_path.with_suffix(f'.{output_format}')

    save_kwargs = {}
    if output_format in ('jpg', 'jpeg'):
      save_kwargs = {'quality': quality, 'optimize': True}
    elif output_format == 'webp':
      save_kwargs = {'quality': quality, 'method': 6}
    elif output_format == 'png':
      save_kwargs = {'optimize': True}

    img.save(output_file, **save_kwargs)

    original_size = input_path.stat().st_size
    new_size = output_file.stat().st_size
    ratio = (1 - new_size / original_size) * 100
    print(f"{input_path.name} ({original_size / 1024:.1f}KB) → "
          f"{output_file.name} ({new_size / 1024:.1f}KB) "
          f"[{'+' if ratio < 0 else '-'}{abs(ratio):.1f}%]")
    return output_file


二、批量转换文件夹
batch_convert_folder(input_dir, output_dir, output_format='jpg', quality=85) 遍历输入目录中的所有支持格式文件,输出到指定目录。对 RGBA 透明图同样做白色背景处理;jpg/jpeg 使用 quality+optimize,webp 使用 quality+method=6。最后统计转换张数和节省空间。


def batch_convert_folder(input_dir, output_dir, output_format='jpg', quality=85):
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    count = 0
    total_saved = 0

    for file_path in input_path.iterdir():
      if file_path.is_file() and file_path.suffix.lower() in SUPPORTED_EXTENSIONS:
            output_file = output_path / f"{file_path.stem}.{output_format}"
            img = Image.open(file_path)
            original_size = file_path.stat().st_size

            if output_format in ('jpg', 'jpeg', 'bmp') and img.mode == 'RGBA':
                background = Image.new('RGB', img.size, (255, 255, 255))
                background.paste(img, mask=img.split())
                img = background

            save_kwargs = {}
            if output_format in ('jpg', 'jpeg'):
                save_kwargs = {'quality': quality, 'optimize': True}
            elif output_format == 'webp':
                save_kwargs = {'quality': quality, 'method': 6}

            img.save(output_file, **save_kwargs)
            new_size = output_file.stat().st_size
            total_saved += original_size - new_size
            count += 1

    print(f"\n批量转换完成: {count} 张图片")
    print(f"节省空间: {total_saved / 1024 / 1024:.2f} MB")


三、批量压缩(保持原格式)
batch_compress_images(input_dir, output_dir, quality=75, max_width=1920, max_height=1080) 遍历 jpg/jpeg/png/webp 文件,先将图片等比缩放到不超过 max_width×max_height,再按质量参数保存。注意:原代码中 save_kwargs 只在 jpg/jpeg 分支定义,若处理 png/webp 会报错;实际使用时需要为 png/webp 补充对应的保存参数。这一点在原作者提供的示例中也未覆盖,读者需留意。


def batch_compress_images(input_dir, output_dir, quality=75, max_width=1920, max_height=1080):
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)

    count = 0
    total_saved = 0

    for file_path in input_path.iterdir():
      if file_path.is_file() and file_path.suffix.lower() in {'.jpg', '.jpeg', '.png', '.webp'}:
            img = Image.open(file_path)

            if max_width and max_height:
                img.thumbnail((max_width, max_height), Image.LANCZOS)

            save_kwargs = {}
            if file_path.suffix.lower() in ('.jpg', '.jpeg'):
                save_kwargs = {'quality': quality, 'optimize': True}
            # 注意:原代码没有处理 png/webp 的保存参数

            output_file = output_path / file_path.name
            img.save(output_file, **save_kwargs)

            original_size = file_path.stat().st_size
            new_size = output_file.stat().st_size
            total_saved += original_size - new_size
            count += 1

    print(f"批量压缩完成: {count} 张图片")
    print(f"节省空间: {total_saved / 1024 / 1024:.2f} MB")


四、使用示例
主入口示范了批量转 WebP 的调用方式。单张转换和批量压缩的调用已注释,按需放开即可。


if __name__ == "__main__":
    # convert_image("photo.png", output_format='jpg', quality=85)
    batch_convert_folder("产品图片", "产品图片_WebP", output_format='webp', quality=80)
    # batch_compress_images("原始照片", "压缩照片", quality=75, max_width=1920)


常见问题:
Q1: GIF 动图转换后不动了?
Pillow 默认只读取 GIF 的第一帧,所以动画会丢失。要保留动画,可以安装 imageio:pip install imageio,然后用 imageio.mimread 读取所有帧,再用 imageio.mimwrite 写出 WebP(duration=0.1 控制帧间隔)。

Q2: JPG 转 PNG 后体积变大很多?
因为 JPG 是有损压缩,PNG 是无损压缩,JPG 转 PNG 会把原本丢失的信息重新“放大”保存,导致体积增加。如果目标是减小体积,反向从 PNG 转 JPG 更合适。

总结:
- 格式转换:img.save('output.jpg') 即可自动按扩展名转换。
- 压缩质量:quality=75 左右能在体积和画质间取得平衡。
- 尺寸缩放:img.thumbnail() 按比例缩小,避免拉伸变形。
- 透明处理:JPG 不支持 alpha 通道,RGBA 转 RGB 时先用白色背景合成。

这样一套脚本可以覆盖日常图片处理需求,在批量转换和压缩场景下替代人工操作,节省大量时间。

热心网友4 发表于 2026-8-31 19:00:00

Re: Python脚本实现Webp PNG JPG图片批量互转与无损压缩

这个脚本写得很实用,正好最近在处理网站图片优化,收藏了。特别是透明通道转白底的处理很贴心,避免了很多时候JPG直接打开透明图会变黑底的问题。想问一下,WebP的method=6在批量大图的时候速度会不会比较慢?有没有考虑加一个线程池或者进度显示的选项?

热心网友4 发表于 2026-8-31 19:00:00

Re: Python脚本实现Webp PNG JPG图片批量互转与无损压缩

这个脚本很实用,正好最近在整理网站图片,手动用PS一张张转太痛苦了。我试了下批量转WebP,体积确实小了很多,尤其是不透明图片。 有个小建议:对于带透明通道的PNG转成JPG时,默认用白底填充有时候会和原图视觉差异较大,如果能在函数里加个参数允许自定义背景色(比如透明转成黑色底或者棋盘格)就更灵活了。另外,批量转换时如果输入目录里有子文件夹的话,目前只会处理当前层级的文件,如果能递归遍历就更方便了。 不过总体逻辑很清晰,尤其是用thumbnail等比缩放那一步,对需要控制最大尺寸的场景非常有用。感谢分享!

热心网友4 发表于 2026-8-31 19:00:00

Re: Python脚本实现Webp PNG JPG图片批量互转与无损压缩

楼主这脚本挺实用的,正好我最近在处理一批网站素材。有个小建议:如果原图是灰度模式或CMYK模式,转换时可能要先转成RGB,不然某些格式会报错;另外批量转换那边如果输入输出目录相同,会不会覆盖原文件?可以考虑加个自动重命名或备份逻辑。总之代码写得很清晰,收藏了。
页: [1]
查看完整版本: Python脚本实现Webp PNG JPG图片批量互转与无损压缩