Skip to content

Python图片处理:我每天都在用的这几个脚本

· 4 min read · Imagic AI Team

用Python自动化处理图片5年了,这些是我每天都在用的脚本。复制粘贴就能用,处理几千张图片几分钟搞定。

Python图片处理:我每天都在用的这几个脚本

我2019年开始用Python处理图片,最开始是帮朋友压缩他电商店铺的500张产品图。现在一天处理几万张都习以为常了。

说真的,学会这几个脚本之后,我再也没打开过Photoshop批量处理图片。


先装个库

pip install Pillow

就一个库,够用了。


脚本1:最基本的压缩

把图片转成WebP格式,文件小一半。

from PIL import Image
from pathlib import Path

def compress_to_webp(input_path, output_path=None, quality=85):
    img = Image.open(input_path)

    # 自动生成输出文件名
    if output_path is None:
        output_path = Path(input_path).with_suffix('.webp')

    # 转RGB(去透明通道,文件更小)
    if img.mode == 'RGBA':
        img = img.convert('RGB')

    # 保存
    img.save(output_path, 'WEBP', quality=quality)

    # 打印结果
    import os
    orig = os.path.getsize(input_path) / 1024
    new = os.path.getsize(output_path) / 1024
    saved = (1 - new / orig) * 100

    print(f"{Path(input_path).name}: {orig:.0f}KB → {new:.0f}KB(节省{saved:.0f}%)")

# 用法
compress_to_webp('photo.jpg', quality=85)

脚本2:缩放+压缩

最常用的场景:先缩到合适大小,再压缩。

from PIL import Image
from pathlib import Path
import os

def resize_and_compress(input_path, output_dir, max_size=1920, quality=85):
    img = Image.open(input_path)

    # 超过最大尺寸才缩放
    if max(img.size) > max_size:
        ratio = max_size / max(img.size)
        new_size = tuple(int(d * ratio) for d in img.size)
        img = img.resize(new_size, Image.Resampling.LANCZOS)
        print(f"  缩放到 {new_size[0]}x{new_size[1]}")

    # 创建输出目录
    output_dir = Path(output_dir)
    output_dir.mkdir(exist_ok=True)

    # 生成输出文件名
    filename = Path(input_path).stem + '.webp'
    output_path = output_dir / filename

    # 转RGB
    if img.mode == 'RGBA':
        img = img.convert('RGB')

    # 保存
    img.save(output_path, 'WEBP', quality=quality)

    # 打印结果
    orig = os.path.getsize(input_path) / 1024
    new = os.path.getsize(output_path) / 1024
    print(f"{Path(input_path).name}: {orig:.0f}KB → {new:.0f}KB(节省{(1-new/orig)*100:.0f}%)")

# 用法
resize_and_compress('photo.jpg', './output', max_size=1920, quality=85)

脚本3:批量处理

这个是我用得最多的。处理一整个文件夹。

from PIL import Image
from pathlib import Path
import os
from concurrent.futures import ThreadPoolExecutor
import time

def batch_process(input_dir, output_dir, max_size=1920, quality=85, workers=4):
    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(exist_ok=True)

    # 找所有图片
    extensions = ('.jpg', '.jpeg', '.png', '.webp', '.bmp')
    images = [f for f in input_path.iterdir() 
              if f.suffix.lower() in extensions]

    print(f"找到 {len(images)} 张图片")
    print(f"最大尺寸: {max_size}px | 质量: {quality}%")
    print("-" * 50)

    def process(img_file):
        try:
            img = Image.open(img_file)

            # 缩放
            if max(img.size) > max_size:
                ratio = max_size / max(img.size)
                img = img.resize(
                    tuple(int(d * ratio) for d in img.size),
                    Image.Resampling.LANCZOS
                )

            # 转RGB
            if img.mode == 'RGBA':
                img = img.convert('RGB')

            # 保存
            out_file = output_path / f"{img_file.stem}.webp"
            img.save(out_file, 'WEBP', quality=quality)

            orig = os.path.getsize(img_file) / 1024
            new = os.path.getsize(out_file) / 1024

            return {'name': img_file.name, 'orig': orig, 'new': new}
        except Exception as e:
            return {'name': img_file.name, 'error': str(e)}

    # 并行处理
    start = time.time()
    results = list(ThreadPoolExecutor(max_workers=workers).map(process, images))

    # 打印统计
    elapsed = time.time() - start
    total_orig = sum(r.get('orig', 0) for r in results)
    total_new = sum(r.get('new', 0) for r in results)
    errors = sum(1 for r in results if 'error' in r)

    print(f"\n处理完成!")
    print(f"总数: {len(results)} | 失败: {errors}")
    print(f"耗时: {elapsed:.1f}秒")
    print(f"大小: {total_orig:.0f}KB → {total_new:.0f}KB")
    print(f"节省: {(1-total_new/total_orig)*100:.0f}%")

# 用法
batch_process('./photos', './optimized', max_size=1920, quality=85, workers=8)

脚本4:PNG优化

PNG图片的处理方式不太一样。

from PIL import Image
from pathlib import Path
import os

def optimize_png(input_path, output_path=None):
    img = Image.open(input_path)

    if output_path is None:
        output_path = Path(input_path)

    orig_size = os.path.getsize(input_path) / 1024

    # 有透明通道的话
    if img.mode in ('RGBA', 'LA', 'P'):
        # 试试PNG优化
        img_opt = Image.new('RGBA', img.size)
        img_opt.putdata(list(img.getdata()))
        img_opt.save(output_path, 'PNG', optimize=True)
        opt_size = os.path.getsize(output_path) / 1024

        # 也试试WebP
        webp_path = output_path.with_suffix('.webp')
        img_rgb = img.convert('RGB') if img.mode == 'RGBA' else img
        img_rgb.save(webp_path, 'WEBP', quality=85)
        webp_size = os.path.getsize(webp_path) / 1024

        # 选小的那个
        if webp_size < opt_size:
            output_path.unlink()
            output_path = webp_path
            print(f"→ 转WebP(更小)")
        else:
            webp_path.unlink()

    new_size = os.path.getsize(output_path) / 1024
    print(f"{Path(input_path).name}: {orig_size:.0f}KB → {new_size:.0f}KB")

    return output_path

# 用法
optimize_png('graphic.png')

脚本5:生成多尺寸版本

做响应式网站必备的,生成不同尺寸的图片。

from PIL import Image
from pathlib import Path

def generate_responsive(input_path, output_dir, sizes=[400, 800, 1200, 1920]):
    img = Image.open(input_path)
    output_dir = Path(output_dir)
    output_dir.mkdir(exist_ok=True)

    filename = Path(input_path).stem

    for size in sizes:
        if img.width >= size:
            ratio = size / img.width
            new_size = (size, int(img.height * ratio))

            resized = img.resize(new_size, Image.Resampling.LANCZOS)

            if resized.mode == 'RGBA':
                resized = resized.convert('RGB')

            output_path = output_dir / f"{filename}_{size}.webp"
            resized.save(output_path, 'WEBP', quality=85)

            print(f"生成 {size}px: {new_size[0]}x{new_size[1]}")

# 用法
generate_responsive('hero.jpg', './responsive', sizes=[400, 800, 1200, 1920])

脚本6:批量生成响应式图片

给不会写代码的朋友用的,直接处理整个文件夹。

from pathlib import Path

def batch_responsive(input_dir, output_dir, widths=[400, 800, 1200]):
    from PIL import Image

    input_path = Path(input_dir)
    output_path = Path(output_dir)
    output_path.mkdir(exist_ok=True)

    images = list(input_path.glob('*.jpg')) + list(input_path.glob('*.png'))
    print(f"处理 {len(images)} 张图片...")

    for img_file in images:
        img = Image.open(img_file)
        filename = img_file.stem

        for width in widths:
            if img.width >= width:
                ratio = width / img.width
                resized = img.resize((width, int(img.height * ratio)), 
                                    Image.Resampling.LANCZOS)
                resized.convert('RGB').save(
                    output_path / f"{filename}_{width}.webp", 
                    'WEBP', quality=85
                )

        print(f"✓ {img_file.name}")

    print("完成!")

# 用法
batch_responsive('./photos', './responsive')

常见问题

Q: 图片糊了怎么办?

A: 质量调高一点试试。quality=85是平衡点,想要更好就95,不在乎就70

Q: 透明背景没了?

A: JPEG不支持透明。把PNG转JPEG的话,透明部分会变成白色。如果需要透明,用WebP格式。

Q: 处理失败了?

A: 可能是图片损坏或者格式不支持。脚本里有try-except,会跳过坏文件继续处理。

Q: 内存不够用?

A: 减少workers数量。8改成4或者2。


总结

  1. Pillow够用了 - 不用装一堆库
  2. WebP是趋势 - 比JPEG小30%,浏览器都支持
  3. 先缩再压 - 不要压完再缩,那没用
  4. 并行处理快 - 8个线程比1个快6-7倍
  5. 测试几个再跑全量 - 免得翻车

快速工具

不想写代码?试试这个:Imagic AI - 浏览器里拖进去就能用


用了5年Python处理图片。有问题留言。

Try these tools

Image Compressor

Related articles

Python Image Compression: Complete Guide with Code ExamplesImage Compression Algorithms Explained - How We Reduce File Size by 80Lossy vs Lossless Compression: What Actually Happens to Your Image