要真正无损批量转换图像,jpeg需设quality=95,png需optimize=false且compress_level=0,webp需lossless=true;heic须用imageio+pyav并手动转rgb;多线程中每个线程须独立open();exif需以二进制形式显式传递。

用 Pillow 批量转换格式但保留原始质量
直接调用 save() 时没指定 quality 参数,JPEG 默认会降质(Pillow 通常设为 75),PNG 则可能因默认 optimize=True 触发有损压缩路径(尤其在某些 Pillow 编译版本中)。要真正“无损”,得按格式分别处理:
- JPEG:显式传
quality=95(95是视觉无损临界值,100反而可能引入微小量化误差) - PNG:关闭优化、禁用抖动、强制使用
mode='RGB'或'RGBA'避免自动转'P'调色板(那是有损的) - WebP:用
lossless=True,别依赖quality=100—— 它仍可能是有损编码
示例关键逻辑:
if img.format == 'JPEG':
img.save(out_path, quality=95, optimize=True)
elif img.format == 'PNG':
img.save(out_path, optimize=False, compress_level=0)
elif img.format == 'WEBP':
img.save(out_path, lossless=True)
imageio + pyav 处理 HEIC/HEIF 等新格式
Pillow 原生不支持 HEIC(iOS 默认照片格式),强行用 Image.open() 会报 OSError: cannot identify image file。必须换库或加插件:
- 装
pyav(FFmpeg 绑定)+imageio-ffmpeg,再用imageio.get_reader()读取 HEIC - 注意:
pyav的decode()返回的是 YUV 帧,需手动转 RGB,否则保存成 JPEG/PNG 会偏色 - 批量时别用
imageio.mimwrite()写 HEIC —— 它不支持写入,只读
简短适配片段:
import imageio
reader = imageio.get_reader('input.HEIC')
for i, frame in enumerate(reader):
rgb_frame = frame.convert('RGB') # 关键!避免 YUV 直出
rgb_frame.save(f'output_{i}.png')
用 concurrent.futures 加速但避开 PIL 线程安全陷阱
Pillow 的 Image 对象不是线程安全的,多线程直接共享一个 Image 实例会导致段错误或图像错乱。常见误操作是把 Image.open() 放在线程外、然后传给多个 worker —— 这不行。
- 正确做法:每个线程内独立调用
Image.open(),处理完立刻.close() - 别用
ThreadPoolExecutor处理超大图(如 >50MP),内存峰值翻倍;改用ProcessPoolExecutor更稳,但启动开销略高 - 对 SSD 用户,I/O 其实比 CPU 更容易成瓶颈,线程数设为
min(8, os.cpu_count() * 2)通常比盲目设 32 更有效
文件名与元数据:批量时别让 exif 消失或乱码
默认 Image.save() 会丢掉 EXIF —— 即使你没动图像内容。如果要保留拍摄时间、GPS、相机型号等,必须显式提取并写回:
- 用
img.info.get('exif', b'')拿原始二进制 EXIF 数据(不是字典!) - 保存时传
exif=exif_bytes参数,别试图用img._getexif()—— 它返回的是解析后字典,不能直接塞进save() - 中文路径或文件名在 Windows 上容易报
UnicodeEncodeError,确保 Python 启动时加-X utf8或环境变量PYTHONIOENCODING=utf-8
EXIF 保留示例:
exif_data = img.info.get('exif', b'')
img.save(out_path, exif=exif_data, quality=95)
无损不是靠“不压缩”,而是靠选对参数和格式语义。最常被忽略的是:HEIC 必须换库、EXIF 是二进制 blob、PIL 多线程必须每个线程自己 open。漏掉任意一点,“无损”就变成自我安慰。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











