python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python图片格式转换

Python实现图片格式(Webp/PNG/JPG)批量互转及无损压缩

作者:小庄-Python办公

这篇文章主要为大家详细介绍了Python如何使用Pillow库批量实现JPG、PNG、WebP等格式互转,同时通过调整quality和thumbnail压缩图片体积,有需要的小伙伴可以了解下

场景引入

手动用画图工具一张一张转换?太慢了。本节用 Python 实现批量格式转换和压缩。

技术原理

Pillow 支持几乎所有常见图片格式:

读取图片(任意格式) → PIL Image 对象 → 保存为指定格式

格式特点适用场景
JPG/JPEG有损压缩,不支持透明照片、产品图
PNG无损压缩,支持透明图标、截图
WebPGoogle 格式,体积小网页图片
BMP无压缩老系统兼容
TIFF无损,支持多层印刷、存档

环境准备

pip install Pillow

完整代码

import os
from pathlib import Path
from PIL import Image
# 支持的图片格式
SUPPORTED_EXTENSIONS = {'.jpg', '.jpeg', '.png', '.webp', '.bmp', '.tiff', '.gif'}
# ==================== 方案 1:单个格式转换 ====================
def convert_image(input_file, output_format='jpg', quality=85, max_size=None):
    """
    转换图片格式
    参数:
        input_file: 输入图片路径
        output_format: 输出格式 'jpg'/'png'/'webp'/'bmp'
        quality: 压缩质量(1-100,仅对 jpg/webp 有效)
        max_size: 最大尺寸 (width, height) 或 None
    """
    input_path = Path(input_file)
    img = Image.open(input_path)
    # 如果需要调整大小
    if max_size:
        img.thumbnail(max_size, Image.LANCZOS)
    # 处理 RGBA → RGB(JPG 不支持透明通道)
    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()[3])
        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
# ==================== 方案 2:批量转换 ====================
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
            # 处理 RGBA → RGB
            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()[3])
                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")
# ==================== 方案 3:批量压缩(不改变格式) ====================
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}
            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")
# ==================== 使用示例 ====================
if __name__ == "__main__":
    # 单个转换
    # convert_image("photo.png", output_format='jpg', quality=85)
    # 批量转 WebP(网页优化)
    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
import imageio

frames = imageio.mimread('animation.gif')
imageio.mimwrite('output.webp', frames, duration=0.1)

Q2:JPG 转 PNG 后体积变大很多?

JPG 是有损压缩,PNG 是无损压缩。JPG → PNG 会"放大"原本被压缩的信息。建议反向转换(PNG → JPG)来减小体积。

总结

操作方法效果
格式转换img.save('output.jpg')自动转换
压缩质量quality=75降低文件大小
缩小尺寸img.thumbnail()等比例缩放
透明处理RGBA → RGBJPG 兼容

到此这篇关于Python实现图片格式(Webp/PNG/JPG)批量互转及无损压缩的文章就介绍到这了,更多相关Python图片格式转换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文