当前位置: 代码网 > it编程>前端脚本>Python > Python实现图片格式(Webp/PNG/JPG)批量互转及无损压缩

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

2026年08月31日 Python 我要评论
场景引入网站需要 webp 格式的图片以提升加载速度客户要求 jpg 格式方便查看系统只接受 png 格式的图标图片太大,需要压缩后发送手动用画图工具一张一张转换?太慢了。本节用 python 实现批

场景引入

  • 网站需要 webp 格式的图片以提升加载速度
  • 客户要求 jpg 格式方便查看
  • 系统只接受 png 格式的图标
  • 图片太大,需要压缩后发送

手动用画图工具一张一张转换?太慢了。本节用 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图片格式转换内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com