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。
总结
- Pillow够用了 - 不用装一堆库
- WebP是趋势 - 比JPEG小30%,浏览器都支持
- 先缩再压 - 不要压完再缩,那没用
- 并行处理快 - 8个线程比1个快6-7倍
- 测试几个再跑全量 - 免得翻车
快速工具
不想写代码?试试这个:Imagic AI - 浏览器里拖进去就能用
用了5年Python处理图片。有问题留言。