如何使用Python和Pillow库批量调整图片尺寸并添加水印?
作者:OpenWorld
时间:2026-07-07
浏览:0
利用Pillow批量调整图片尺寸时应使用thumbnail()等比缩放,避免比例扭曲;文字水印需新建RGBA图层用alpha_composite()合成实现透明;批量处理建议使用pathlib和glob过滤文件;中文字体渲染需提前验证字体文件,否则会显示方框。
直接用Pillow批量缩放图片+加水印完全可行,不过有几个环节得花点心思手动处理——透明度、位置、字体渲染,一个不留神就容易卡住。ImageDraw.text()默认不支持透明文字,Image.alpha_composite()又要求两张图的mode严格匹配,这两点是最容易翻车的。
用Pillow批量处理图片确实能省不少事,但关键在于:你得清楚每个工具的特性,否则写出来的脚本要么比例扭曲,要么水印一团黑。下面把几个容易踩坑的地方拆开说。
#### 尺寸调整:别一上来就用`resize()`,`thumbnail()`才是正道
很多新手习惯直接调`resize()`硬拉尺寸,结果遇到宽高比不同的原图就惨了——人物被压扁,风景被拉长。实际上`thumbnail()`才是为批量缩放设计的:它原地等比缩略,只改大不改小,自动适配目标最大边长。比如:
- `img.thumbnail((800, 600), Image.Resampling.LANCZOS)` —— 缩到最长边不超过800px,宽高比完整保留
- 如果你非要统一输出800×600,缩完后再用`img.crop()`居中裁切,别去碰`resize()`的`box`参数,那东西容易把人绕晕
- 另外,批量处理时先执行`img.convert("RGB")`,否则一张RGBA的PNG图片直接在保存JPEG时会报`cannot write mode RGBA as JPEG`,这种错误排查起来特别烦
#### 文字水印:绕过`text()`的透明缺陷,用`Image.new()`+`alpha_composite()`
`ImageDraw.text()`渲染的文字没法直接设透明度,就算你把`fill`写成`(255,255,255,32)`,Pillow也会无视alpha通道。正确的做法是分两层画:
1. 先新建一个与原图同尺寸的RGBA图层作为水印层:`Image.new("RGBA", img.size)`
2. 在这个水印层上用`ImageDraw.Draw(watermark).text()`写字,`fill=(255,255,255,32)`里的32就是alpha值(范围0–255),这样就能控制透明度了
3. 然后把原图转成RGBA:`img.convert("RGBA")`,再用`Image.alpha_composite(img, watermark)`合成,最后转回RGB保存
4. 字体路径必须给绝对路径,`ImageFont.truetype()`不认识相对路径,也不认系统字体名(比如写"Arial"根本没用)
#### 批量循环:别再拿`os.listdir()`硬扫了,换成`pathlib.Path`+`glob()`
`os.listdir()`不过滤隐藏文件,也不区分文件类型,很容易把`.DS_Store`或者子目录当图片处理。改用`pathlib`不仅代码更干净,还能避免这些坑:
```python
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.sa ve(f"output/{img_path.stem}_wm.jpg")
```
- `glob("*.jpg")`自动过滤非JPG文件,`is_file()`排除目录
- 保存路径用`f"output/{img_path.stem}_wm.jpg"`,`stem`能去掉后缀,避免出现`photo.jpg_wm.jpg`这种双扩展名
- 务必用`with Image.open()`上下文管理,否则批量处理时文件句柄泄漏,跑着跑着就报错
真正麻烦的其实还是中文字体渲染——Pillow对中文支持很弱,`text()`遇到缺字不会报错,只会默默画一堆方框。千万不能只看字体文件名带个“simhei”就以为能用,必须提前验证字体文件是否包含你需要的那几个汉字。
本文内容来源于互联网,如有侵权请联系删除。
用Pillow批量处理图片确实能省不少事,但关键在于:你得清楚每个工具的特性,否则写出来的脚本要么比例扭曲,要么水印一团黑。下面把几个容易踩坑的地方拆开说。
#### 尺寸调整:别一上来就用`resize()`,`thumbnail()`才是正道
很多新手习惯直接调`resize()`硬拉尺寸,结果遇到宽高比不同的原图就惨了——人物被压扁,风景被拉长。实际上`thumbnail()`才是为批量缩放设计的:它原地等比缩略,只改大不改小,自动适配目标最大边长。比如:
- `img.thumbnail((800, 600), Image.Resampling.LANCZOS)` —— 缩到最长边不超过800px,宽高比完整保留
- 如果你非要统一输出800×600,缩完后再用`img.crop()`居中裁切,别去碰`resize()`的`box`参数,那东西容易把人绕晕
- 另外,批量处理时先执行`img.convert("RGB")`,否则一张RGBA的PNG图片直接在保存JPEG时会报`cannot write mode RGBA as JPEG`,这种错误排查起来特别烦
#### 文字水印:绕过`text()`的透明缺陷,用`Image.new()`+`alpha_composite()`
`ImageDraw.text()`渲染的文字没法直接设透明度,就算你把`fill`写成`(255,255,255,32)`,Pillow也会无视alpha通道。正确的做法是分两层画:
1. 先新建一个与原图同尺寸的RGBA图层作为水印层:`Image.new("RGBA", img.size)`
2. 在这个水印层上用`ImageDraw.Draw(watermark).text()`写字,`fill=(255,255,255,32)`里的32就是alpha值(范围0–255),这样就能控制透明度了
3. 然后把原图转成RGBA:`img.convert("RGBA")`,再用`Image.alpha_composite(img, watermark)`合成,最后转回RGB保存
4. 字体路径必须给绝对路径,`ImageFont.truetype()`不认识相对路径,也不认系统字体名(比如写"Arial"根本没用)
#### 批量循环:别再拿`os.listdir()`硬扫了,换成`pathlib.Path`+`glob()`
`os.listdir()`不过滤隐藏文件,也不区分文件类型,很容易把`.DS_Store`或者子目录当图片处理。改用`pathlib`不仅代码更干净,还能避免这些坑:
```python
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.sa ve(f"output/{img_path.stem}_wm.jpg")
```
- `glob("*.jpg")`自动过滤非JPG文件,`is_file()`排除目录
- 保存路径用`f"output/{img_path.stem}_wm.jpg"`,`stem`能去掉后缀,避免出现`photo.jpg_wm.jpg`这种双扩展名
- 务必用`with Image.open()`上下文管理,否则批量处理时文件句柄泄漏,跑着跑着就报错
真正麻烦的其实还是中文字体渲染——Pillow对中文支持很弱,`text()`遇到缺字不会报错,只会默默画一堆方框。千万不能只看字体文件名带个“simhei”就以为能用,必须提前验证字体文件是否包含你需要的那几个汉字。
作者最新文章
三星 Galaxy A08 渲染图曝光:Helio G99 芯片与 6000mAh 电池配置解析
2026-09-08 17:14
OPPO Find X10 Pro Max 影像规格详解:三颗2亿像素镜头与全焦段8K视频能力
2026-09-08 16:41
PDF转HTML在线转换器怎么选?转换后网页排版怎么查?
2026-09-04 11:02
AE教程书籍挑选指南:零基础、动效与合成方向实战标准
2026-09-02 13:31
教程书籍使用SAI软件Logo要单独授权吗:商标引用与出版合规要点
2026-09-02 11:50
热门文章
更多
精品专题
更多
Mac软件
更多
WINDOWS
更多


































