当前位置: 代码网 > it编程>前端脚本>Python > Python实现批量压缩图片的实用脚本分享

Python实现批量压缩图片的实用脚本分享

2026年02月02日 Python 我要评论
引言:为什么需要批量压缩图片?手机拍摄的4k照片动辄10mb,单反相机拍摄的raw格式图片更是高达50mb以上。当需要分享旅行照片、上传电商产品图或管理设计素材库时,庞大的图片体积会带来诸多困扰:云存

引言:为什么需要批量压缩图片?

手机拍摄的4k照片动辄10mb,单反相机拍摄的raw格式图片更是高达50mb以上。当需要分享旅行照片、上传电商产品图或管理设计素材库时,庞大的图片体积会带来诸多困扰:云存储空间快速耗尽、网页加载速度变慢、邮件发送附件受限……批量压缩图片成为解决这些问题的关键手段。

通过python脚本实现自动化压缩,不仅能精准控制压缩参数,还能批量处理成百上千张图片。相比在线工具,本地脚本无需上传隐私图片,处理速度更快;相比专业软件,python方案无需付费且可高度定制。本文将通过实际案例,展示如何用50行代码构建高效图片压缩工具。

一、核心原理:如何实现图片压缩?

图片压缩主要通过两种技术路径实现,python的pillow库完美支持这两种方式:

1. 尺寸压缩:降低分辨率

原始图片尺寸为4000×3000像素,若目标设备仅需1920×1080显示,直接缩小尺寸可减少75%像素量。pillow的thumbnail()方法能自动保持宽高比进行缩放:

from pil import image
img = image.open("photo.jpg")
img.thumbnail((1920, 1080))  # 保持比例缩放

2. 质量压缩:优化编码

jpeg格式通过调整质量参数(1-100)控制压缩强度。质量值越低,文件越小但可能产生噪点。实测显示,质量85时人眼难以察觉差异,但文件体积可减少60%:

img.save("compressed.jpg", quality=85, optimize=true)

3. 智能组合策略

最佳实践是同时应用尺寸和质量压缩。例如将4000×3000图片缩小至1920×1440后,再设置质量85,实测5.2mb原图可压缩至320kb,体积减少94%而肉眼几乎无差别。

二、基础脚本:50行代码实现批量压缩

以下脚本支持递归处理子目录,自动创建输出文件夹,并显示压缩进度:

import os
from pil import image
from pathlib import path

def compress_image(input_path, output_path, max_size=1920, quality=85):
    """压缩单张图片"""
    try:
        with image.open(input_path) as img:
            # 转换模式处理透明通道
            if img.mode in ("rgba", "p"):
                img = img.convert("rgb")
            
            # 按比例缩放
            img.thumbnail((max_size, max_size), image.lanczos)
            
            # 保存为jpeg格式
            output_path = output_path.with_suffix('.jpg')
            img.save(output_path, "jpeg", optimize=true, quality=quality)
            
            # 计算压缩率
            orig_size = os.path.getsize(input_path)
            new_size = os.path.getsize(output_path)
            ratio = (1 - new_size / orig_size) * 100
            print(f"✅ {path(input_path).name}: {orig_size//1024}kb → {new_size//1024}kb (节省{ratio:.1f}%)")
            
    except exception as e:
        print(f"❌ 压缩失败 {input_path}: {e}")

def batch_compress(input_folder, output_folder, max_size=1920, quality=85):
    """批量处理文件夹"""
    input_path = path(input_folder)
    output_path = path(output_folder)
    output_path.mkdir(parents=true, exist_ok=true)

    # 支持的图片格式
    supported_ext = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff')
    
    # 遍历所有图片文件
    image_files = [
        f for f in input_path.rglob('*') 
        if f.suffix.lower() in supported_ext and f.is_file()
    ]

    if not image_files:
        print("⚠️ 指定文件夹中没有可处理的图片")
        return

    print(f"🔍 找到 {len(image_files)} 张图片,开始压缩...")
    for img_file in image_files:
        rel_path = img_file.relative_to(input_path)
        out_file = output_path / rel_path.with_stem(f"{rel_path.stem}_compressed")
        compress_image(img_file, out_file, max_size, quality)

    print(f"\n🎉 全部完成!压缩后图片保存在: {output_folder}")

if __name__ == "__main__":
    batch_compress("./photos", "./compressed", max_size=1200, quality=75)

脚本特性说明:

  1. 智能路径处理:使用path.rglob()递归查找所有子目录中的图片
  2. 透明通道处理:自动将png的rgba模式转换为rgb,避免jpeg保存错误
  3. 进度可视化:实时显示每张图片的压缩前后大小及节省比例
  4. 安全设计:输出路径自动创建,避免因目录不存在导致的错误

三、进阶优化:满足不同场景需求

1. 动态质量调整(ssim算法)

对于需要极致压缩的场景,可通过结构相似性(ssim)评估图片质量损失,动态调整压缩参数:

from math import log
from ssim_pil import compare_ssim  # 需安装pyssim库

def get_ssim_at_quality(photo, quality):
    """计算指定质量下的ssim值"""
    temp_path = "temp.jpg"
    photo.save(temp_path, format="jpeg", quality=quality, progressive=true)
    ssim_score = compare_ssim(photo, image.open(temp_path))
    os.remove(temp_path)
    return ssim_score

def find_optimal_quality(original_photo, target_ssim=0.95):
    """二分法寻找最优质量参数"""
    low, high = 70, 95
    while high - low > 2:
        mid = (high + low) // 2
        if get_ssim_at_quality(original_photo, mid) < target_ssim:
            low = mid
        else:
            high = mid
    return high

# 使用示例
img = image.open("photo.jpg")
optimal_quality = find_optimal_quality(img)
img.save("optimized.jpg", quality=optimal_quality)

2. 格式转换优化

对于截图、图标等简单图形,转换为png格式并启用调色板优化可获得更好效果:

def compress_png(input_path, output_path, palette_size=256):
    """png无损压缩"""
    img = image.open(input_path)
    if img.mode == "rgb":
        # 生成最优调色板
        palleted_img = img.convert(
            'p', 
            palette=image.adaptive, 
            colors=palette_size
        )
        palleted_img.save(
            output_path, 
            optimize=true,
            compress_level=9  # 最大压缩级别
        )

3. 多线程加速处理

处理大量图片时,使用多线程可显著提升速度:

from concurrent.futures import threadpoolexecutor

def parallel_compress(input_folder, output_folder, max_workers=4):
    """多线程压缩"""
    image_files = [f for f in path(input_folder).rglob('*') 
                  if f.suffix.lower() in ('.jpg', '.png') and f.is_file()]
    
    with threadpoolexecutor(max_workers=max_workers) as executor:
        for img_file in image_files:
            rel_path = img_file.relative_to(input_folder)
            out_file = path(output_folder) / rel_path.with_stem(f"{rel_path.stem}_compressed")
            executor.submit(
                compress_image, 
                img_file, 
                out_file, 
                max_size=1200, 
                quality=75
            )

四、实战案例:电商图片处理流程

某电商团队需要处理5000张产品图,要求:

  1. 统一尺寸为800×800像素
  2. jpeg质量设置为80
  3. 保留原始文件名并添加"_web"后缀
  4. 生成处理报告

解决方案:

import pandas as pd
from datetime import datetime

def ecommerce_compress(input_folder, output_folder):
    """电商图片专用压缩流程"""
    results = []
    start_time = datetime.now()
    
    for img_file in path(input_folder).rglob('*.jpg'):
        try:
            # 创建输出路径
            rel_path = img_file.relative_to(input_folder)
            out_file = path(output_folder) / rel_path.with_stem(f"{rel_path.stem}_web")
            out_file.parent.mkdir(parents=true, exist_ok=true)
            
            # 压缩处理
            with image.open(img_file) as img:
                # 强制正方形裁剪(需先安装opencv-python)
                # import cv2
                # img = cv2.resize(np.array(img), (800,800))
                # img = image.fromarray(img)
                
                # 简单缩放方案
                img.thumbnail((800, 800), image.lanczos)
                img.save(out_file, "jpeg", quality=80, optimize=true)
            
            # 记录结果
            results.append({
                "文件名": img_file.name,
                "原始大小(kb)": os.path.getsize(img_file)//1024,
                "压缩后(kb)": os.path.getsize(out_file)//1024,
                "状态": "成功"
            })
            
        except exception as e:
            results.append({
                "文件名": img_file.name,
                "原始大小(kb)": "-",
                "压缩后(kb)": "-",
                "状态": f"失败: {str(e)}"
            })
    
    # 生成报告
    df = pd.dataframe(results)
    report_path = path(output_folder) / f"压缩报告_{datetime.now().strftime('%y%m%d')}.csv"
    df.to_csv(report_path, index=false)
    
    print(f"\n处理完成!耗时: {(datetime.now()-start_time).seconds}秒")
    print(f"详细报告已生成: {report_path}")

# 使用示例
ecommerce_compress("./raw_images", "./web_images")

五、常见问题解决方案

1. 处理透明背景图片

错误做法:直接保存为jpeg会丢失透明通道
正确方案:

def handle_transparency(input_path, output_path):
    img = image.open(input_path)
    if img.mode == "rgba":
        # 创建白色背景
        background = image.new("rgb", img.size, (255, 255, 255))
        background.paste(img, mask=img.split()[-1])
        background.save(output_path, "jpeg", quality=85)
    else:
        img.save(output_path, "jpeg", quality=85)

2. 保留exif信息

使用piexif库可保留照片的拍摄参数:

import piexif

def save_with_exif(img, output_path, quality=85):
    """保存图片并保留exif信息"""
    exif_dict = piexif.load(img.info['exif']) if 'exif' in img.info else {}
    img.save(
        output_path, 
        "jpeg", 
        quality=quality,
        exif=piexif.dump(exif_dict)
    )

3. 处理超大图片

对于超过100mb的tiff格式图片,需先分块处理:

from pil import imagesequence

def process_large_tiff(input_path, output_path):
    """分块处理超大tiff文件"""
    with image.open(input_path) as img:
        for i, page in enumerate(imagesequence.iterator(img)):
            page.thumbnail((4000, 4000))  # 先缩小尺寸
            page.save(
                f"{output_path}_page{i}.jpg",
                "jpeg",
                quality=80,
                optimize=true
            )

六、性能对比:不同压缩方案效率

方案处理速度压缩率质量损失适用场景
单纯尺寸压缩★★★★★网页显示
质量85压缩★★★★轻微电商产品图
ssim动态质量调整★★★极高极小高端摄影作品
png调色板优化★★简单图形/图标
多线程处理★★★★★同单线程批量处理

实测数据显示:5000张图片处理时,单线程需2小时,8线程方案仅需25分钟。

七、总结:构建个性化图片处理流水线

通过组合本文介绍的技术模块,可构建满足不同需求的图片处理系统:

  1. 基础版:尺寸+质量压缩(适合大多数场景)
  2. 电商版:正方形裁剪+水印添加+exif保留
  3. 摄影版:ssim动态质量+渐进式jpeg
  4. 极速版:多线程处理+缓存机制

建议从基础脚本开始,根据实际需求逐步添加功能模块。对于非技术用户,可使用pyinstaller将脚本打包为exe文件,无需安装python环境即可运行。

图片压缩的本质是在文件体积与视觉质量间寻找平衡点。掌握这些技术后,您不仅能节省存储空间,更能为网站加速、移动应用优化等场景提供关键支持。

以上就是python批量压缩图片的实用脚本分享的详细内容,更多关于python批量压缩图片的资料请关注代码网其它相关文章!

(0)

相关文章:

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

发表评论

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