Pillow.Image.resize()仅改变分辨率,不减小文件体积;真正压缩需在save()时设置quality(JPEG)或optimize/quantize(PNG)等编码参数。

单纯用 Pillow.Image.resize() 无法“不失真地压缩图片大小”——它只改变尺寸,不控制文件体积,还可能因插值引入模糊或锯齿。 真正要减小文件体积(即“压缩大小”),必须调整保存时的编码参数,比如 quality(JPEG)或 optimize/bits(PNG),而 resize() 只是预处理环节之一。
为什么 resize() 不等于压缩文件大小
resize() 仅重采样像素网格,输出图像的像素数变少,但若仍以高画质、无损方式保存(如 quality=95 或 PNG 默认),文件体积未必下降,甚至因新尺寸导致压缩效率变差(例如从 1920×1080 缩到 1919×1079,破坏 JPEG MCU 对齐,反而增大体积)。
- 常见错误现象:
img.resize((800, 600)).save("out.jpg")后文件比原图还大 - 根本原因:没传
quality,PIL 默认用最高质量(quality=95)保存 JPEG - 正确思路:先 resize 控制分辨率,再用有损/优化参数保存
批量压缩 JPEG:resize + quality + progressive
对照片类图片,优先用 JPEG 格式,靠 quality 和渐进式编码平衡体积与观感:
from PIL import Image
<p>def compress_jpeg_batch(input_paths, output_dir, max_size=(1200, 800), quality=80):
for path in input_paths:
with Image.open(path) as img:</p><h1>保持宽高比缩放,不超过 max_size</h1><pre class="brush:php;toolbar:false;"> img.thumbnail(max_size, Image.Resampling.LANCZOS)
# 转为 RGB(避免 RGBA 保存为 JPEG 报错)
if img.mode in ("RGBA", "LA", "P"):
background = Image.new("RGB", img.size, (255, 255, 255))
background.paste(img, mask=img.split()[-1] if img.mode == "RGBA" else None)
img = background
# 保存时启用渐进式和压缩
out_path = f"{output_dir}/{path.stem}_q{quality}.jpg"
img.save(out_path, "JPEG", quality=quality, progressive=True, optimize=True)
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
立即学习“Python免费学习笔记(深入)”;
-
Image.Resampling.LANCZOS比默认的NEAREST更保细节,适合降质前的缩放 -
optimize=True强制 Huffman 表优化,通常省 5–10% 体积 -
progressive=True对网页加载友好,但某些老旧查看器可能不兼容 - 别设
quality > 90—— 80–85 是人眼难辨失真的性价比拐点
批量压缩 PNG:resize + quantize + optimize
PNG 本质无损,但可转为索引色(quantize)大幅减体积,尤其适合图标、截图等颜色数少的图:
def compress_png_batch(input_paths, output_dir, max_size=(800, 600)):
for path in input_paths:
with Image.open(path) as img:
img.thumbnail(max_size, Image.Resampling.LANCZOS)
# 转为 RGB 再转 P 模式(支持 alpha 的量化需额外处理)
if img.mode == "RGBA":
img = img.convert("RGBA").convert("P", palette=Image.Palette.ADAPTIVE, colors=256)
else:
img = img.convert("RGB").convert("P", palette=Image.Palette.ADAPTIVE, colors=256)
out_path = f"{output_dir}/{path.stem}_opt.png"
img.save(out_path, optimize=True, pnginfo=img.info)
-
colors=256是关键——限制调色板大小,比默认的 256 色更激进时可用 128,但可能出色带 -
optimize=True对 PNG 必须开启,否则不压缩 IDAT 块 - 含透明通道的 PNG 若直接
convert("P")会丢 alpha,得用palette=Image.Palette.ADAPTIVE配合colors - 别依赖
pnginfo保存元数据——多数压缩场景下应丢弃 EXIF/XMP
真正影响最终体积的,从来不是 resize() 本身,而是你是否在 save() 时主动干预编码行为。很多人卡在“缩了但文件没小”,问题就出在忘了传 quality 或 optimize;还有人盲目追求高 quality,却不知道 80 和 90 在 1080p 屏上几乎看不出区别,但体积可能差一倍。

















