PNG文件变大是因为默认未启用优化,需显式设置optimize=True、清除元数据(img.info.clear())、转换颜色模式(如RGB/P)并避免RGBA冗余通道。

用 PIL.Image 打开并保存 PNG 时为什么文件反而变大?
直接用 Image.save("out.png") 默认不启用 PNG 压缩,且可能写入未压缩的 IDAT 数据块。关键参数是 optimize=True 和 compress_level=9,但注意:PIL 的 compress_level 对 PNG 实际无效(只影响 ZIP 压缩层,而 PIL 内部调用的是 zlib,该参数在部分 Pillow 版本中被忽略)。
真正起效的是:optimize=True(触发像素重排和更优过滤器) + 确保不带多余元数据(如 EXIF、ICC Profile)。
- 务必用
img = Image.open(path).convert("RGB")或"P"显式转换模式,避免 RGBA 图片强制保留 alpha 通道导致体积激增 - 用
img.info.clear()清掉原始元数据,否则 ICC/EXIF 会原样复制过去 - 不要依赖
quality参数——PNG 不支持 JPEG 那种有损 quality,设了也无效
批量遍历 PNG 文件时怎么避开子目录或只进一层?
用 pathlib.Path 最稳。默认 rglob("*.png") 会递归所有子目录;如果只要当前文件夹,改用 glob("*.png")。
常见误操作是混用 os.listdir() 和字符串拼接路径,容易漏掉隐藏文件、编码错误或跨平台路径分隔符问题。
立即学习“Python免费学习笔记(深入)”;
- 推荐写法:
list(Path("your_folder").glob("*.png")) - 要排除 macOS 的
.DS_Store或临时文件?加过滤:[p for p in folder.glob("*.png") if not p.name.startswith(".")] - 想安全覆盖原图又防误删?先写到临时文件,再
os.replace()原子替换
pngquant 命令行比 PIL 更省心?什么时候该切过去?
当你要做有损压缩(比如允许轻微色偏换 70% 体积下降),pngquant 是事实标准。它用感知量化算法,比 PIL 的纯无损优化激进得多。
Python 调用它不难,但得先确认系统已安装:pngquant --version 返回正常才可用。
- 调用示例:
subprocess.run(["pngquant", "--force", "--output", str(out_path), str(in_path)]) -
--force覆盖输出文件,--speed 1开启最高压缩(更慢但更小),默认--speed 3 - 注意:pngquant 输出的是 8-bit PNG,若原图是 16-bit 或含 alpha,需加
--alpha参数保留透明度 - 失败时
subprocess.run(..., check=True)会抛异常,别忘了捕获CalledProcessError
Windows 下中文路径报错 OSError: cannot open resource 怎么办?
这通常不是编码问题,而是 Pillow 在 Windows 上加载字体或处理路径时内部用了旧式 C API。根本解法是:所有路径对象统一用 pathlib.Path 构造,且全程不转成 str 传给 Image.open()。
哪怕路径含中文、空格、emoji,Image.open(Path("测试/图片.png")) 也能正常工作;但 Image.open(str(Path("测试/图片.png"))) 在某些 Pillow 版本下就崩。
- 读取前加一行:
assert in_path.exists() and in_path.is_file(),提前暴露路径问题 - 用
try/except OSError as e:捕获并打印e.__cause__,常能看到底层 zlib 或 libpng 的真实错误 - 虚拟环境里 Pillow 版本太老(如 8.x)易出这问题,升级到 10.3+ 可缓解


















