直接用pillow批量缩放图片+加水印完全可行,但必须手动控制透明度、位置和字体渲染逻辑——imagedraw.text()默认不支持透明文字,image.alpha_composite()又要求两张图mode严格匹配;批量缩放应优先用thumbnail()等比缩略而非resize()硬拉;添加文字水印需新建rgba水印层并设置fill=(255,255,255,32)中的alpha值,再通过alpha_composite合成;字体路径须为绝对路径;推荐用pathlib.path.glob()替代os.listdir()提升健壮性;中文字体需提前验证汉字覆盖率,避免静默方框。

直接用 Pillow 批量缩放图片+加水印完全可行,但必须手动控制透明度、位置和字体渲染逻辑——ImageDraw.text() 默认不支持透明文字,Image.alpha_composite() 又要求两张图 mode 严格匹配,这两点最容易卡住。
批量调整尺寸:别用 resize() 硬拉,优先选 thumbnail()
硬调 resize() 会强行扭曲比例,尤其处理不同宽高比的原始图时。而 thumbnail() 是原地等比缩略,只改大不改小,且自动适配目标最大边长:
-
img.thumbnail((800, 600), Image.Resampling.LANCZOS)—— 缩到最长边 ≤800px,保持宽高比 - 缩完后若需居中裁切(比如统一输出 800×600),再用
img.crop()计算坐标,别依赖resize()的box参数 - 批量处理时先
img.convert("RGB")再操作,避免 RGBA 图在保存为 JPEG 时报cannot write mode RGBA as JPEG
添加文字水印:绕过 text() 透明缺陷,用 Image.new() + alpha_composite()
ImageDraw.text() 渲染的文字无法直接设 alpha,强行改 fill 的 RGBA 值也无效。正确做法是分两层画:
- 新建一个与原图同尺寸的
Image.new("RGBA", img.size)作为水印层 - 用
ImageDraw.Draw(watermark).text()在该层上写字,fill=(255,255,255,32)中的 32 就是 alpha 值(0–255) - 最后
img.convert("RGBA")→Image.alpha_composite(img, watermark)→ 转回"RGB"保存 - 字体路径必须是绝对路径,
ImageFont.truetype()不认相对路径或系统字体名(如 "Arial")
批量处理循环:用 os.listdir() 不够健壮,改用 pathlib.Path + glob()
os.listdir() 不过滤隐藏文件、不区分文件类型,容易把 .DS_Store 或目录当图片处理。用 pathlib 更可靠:
from pathlib import Path
img_dir = Path("input")
for img_path in img_dir.glob("*.jpg"): # 或 **/*.png 支持子目录
if img_path.is_file():
with Image.open(img_path) as img:
# 处理逻辑...
img.save(f"output/{img_path.stem}_wm.jpg")
-
glob("*.jpg")自动忽略非 JPG 文件,is_file()排除目录 - 保存路径用
f"output/{img_path.stem}_wm.jpg",stem去掉后缀,避免双重扩展名 - 务必用
with Image.open()上下文管理,防止批量时文件句柄泄漏
真正麻烦的是中文字体渲染——Pillow 对中文支持弱,text() 遇到缺字会静默失败,只画出方框。必须提前验证字体文件是否包含所需汉字,不能只看文件名带“simhei”就以为能用。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











