imageio是读取写入gif等格式最稳方案,兼容png/jpeg/gif,内存可控,支持分块写入与subrectangles优化;需统一尺寸、处理alpha通道、避免中文路径及奇数宽高。

用 imageio 读取+写入是最稳的方案
直接上手推荐 imageio,它对 PNG/JPEG/GIF 格式兼容好,内存控制比 PIL.ImageSequence 更可控,尤其适合几百张图的批量合成。别用 matplotlib.animation——它生成 GIF 是绕路导出帧再调用外部工具,容易卡死或丢帧。
关键点:imageio.mimsave() 的 duration 单位是秒(不是毫秒),且传入的是单个数值或列表;若传列表,长度必须和图片帧数一致。
-
duration=0.1表示每帧显示 100ms;设成[0.05, 0.05, 0.5]可让前两帧快闪、第三帧停顿 - 默认不压缩,生成文件可能很大;加参数
palettesize=256能强制用 256 色调色板,体积通常能压到 1/3 - 如果图片尺寸不一致,
imageio不会自动缩放或裁剪,会直接报错ValueError: All images must have same shape
用 PIL 手动统一尺寸+处理透明通道
很多截图或手机拍的图尺寸杂乱,PNG 还带 alpha 通道,而 GIF 不支持半透明——直接喂给 imageio 会变黑边或颜色错乱。得先用 PIL 统一处理。
核心逻辑:读图 → 转 RGB(丢弃 alpha 或用白底合成)→ resize 到统一宽高 → 存为临时 numpy 数组或直接 append 到列表。
- 避免用
.convert('P')提前转索引色,GIF 编码器自己会做,提前转反而失真 - 合成白底的写法:
background = Image.new('RGB', img.size, (255,255,255)); background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None) - 批量 resize 时别用
Image.ANTIALIAS(已弃用),改用Image.LANCZOS
遇到 OSError: encoder error -2 怎么办
这是 imageio 底层用的 freeimage 或 ffmpeg 编码器崩了,90% 是某张图损坏、路径含中文、或尺寸含奇数像素(尤其老版本 imageio 对 GIF 宽高要求偶数)。
- 先用
try/except包住单张读取,打印出错文件名:imageio.imread(path)报错就跳过 - Windows 下路径含中文会导致
freeimage直接静默失败,统一用pathlib.Path(path).resolve().as_posix()转斜杠+绝对路径 - 检查所有图的
img.size,用max(w//2*2, 2), max(h//2*2, 2)确保宽高为偶数(GIF 规范友好)
大图多帧时内存爆掉?用生成器+分块写入
读 500 张 1080p 图进内存,轻松吃掉 4GB+;imageio.mimsave() 默认全帧加载,不支持流式写入。必须手动切片。
做法:把图片列表按每 50 张一组,用 imageio.get_writer() 创建 writer,循环 .append_data(),最后 .close()。这样内存只留当前块。
- 注意
fps参数在get_writer()里是无效的,得靠duration=1/fps控制 - 不要在循环里反复开闭 writer,每个 writer 对应一个输出文件;想合并在一个 GIF 就只开一次 writer
- 如果帧间差异小(比如监控截图),可加
subrectangles=True让编码器只存变化区域,体积能减 60%+
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











