日常办公和开发中,图片处理的需求非常多------批量改尺寸、加水印、格式转换、压缩大小。用 Python 的 Pillow(PIL 的升级版)可以一键搞定几百张图片的重复操作。
一、安装
bash
pip install Pillow
python
from PIL import Image, ImageDraw, ImageFont, ImageFilter
二、基础操作
1. 打开与显示
python
from PIL import Image
# 打开图片
img = Image.open("照片.jpg")
print(f"格式: {img.format}")
print(f"尺寸: {img.size}") # (宽度, 高度)
print(f"模式: {img.mode}") # RGB、RGBA、L(灰度)等
# 显示图片(会弹出默认图片查看器)
img.show()
# 保存为其他格式
img.save("照片.png")
2. 调整尺寸
python
# 等比例缩放(指定宽度,高度自动计算)
def resize_by_width(img, target_width=800):
w, h = img.size
ratio = target_width / w
new_h = int(h * ratio)
return img.resize((target_width, new_h), Image.LANCZOS)
# 裁剪为正方形(从中心切)
def crop_square(img):
w, h = img.size
min_side = min(w, h)
left = (w - min_side) // 2
top = (h - min_side) // 2
right = left + min_side
bottom = top + min_side
return img.crop((left, top, right, bottom))
# 强制缩放到指定尺寸(会变形)
img_resized = img.resize((1920, 1080), Image.LANCZOS)
# 按比例缩放
img.thumbnail((800, 600)) # 原图会被修改,最长边不超过800或600
3. 旋转与翻转
python
# 旋转(expand=True 防止裁剪)
rotated = img.rotate(90, expand=True)
# 翻转
flipped_h = img.transpose(Image.FLIP_LEFT_RIGHT) # 水平翻转
flipped_v = img.transpose(Image.FLIP_TOP_BOTTOM) # 垂直翻转
三、实战案例:批量处理婚纱照
你刚拍了婚纱照,可以用脚本批量处理:
python
from PIL import Image, ImageFilter
import os
class PhotoProcessor:
"""婚纱照批量处理器"""
def __init__(self, input_dir, output_dir):
self.input_dir = input_dir
self.output_dir = output_dir
os.makedirs(output_dir, exist_ok=True)
def resize_for_wechat(self, max_width=1080):
"""
批量压缩到适合微信分享的尺寸
微信发送原图有限制,先统一压缩
"""
for f in os.listdir(self.input_dir):
if not f.lower().endswith((".jpg", ".jpeg", ".png")):
continue
img = Image.open(os.path.join(self.input_dir, f))
# 等比例缩放到最长边不超过 max_width
w, h = img.size
if max(w, h) > max_width:
ratio = max_width / max(w, h)
new_size = (int(w * ratio), int(h * ratio))
img = img.resize(new_size, Image.LANCZOS)
# 保存(压缩质量 85,既清晰又小)
output_path = os.path.join(self.output_dir, f"wechat_{f}")
img.save(output_path, quality=85, optimize=True)
print(f"已处理: {f} → {output_path}")
def add_watermark(self, text="张政 & 爱妻", position="右下角"):
"""
批量添加水印(保护版权)
"""
for f in os.listdir(self.input_dir):
if not f.lower().endswith((".jpg", ".jpeg", ".png")):
continue
img = Image.open(os.path.join(self.input_dir, f)).convert("RGBA")
# 创建水印层
watermark = Image.new("RGBA", img.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark)
# 字体(Windows 系统字体路径)
font_size = max(img.size) // 30
try:
font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", font_size)
except:
font = ImageFont.load_default()
# 计算文字宽高
bbox = draw.textbbox((0, 0), text, font=font)
text_w = bbox[2] - bbox[0]
text_h = bbox[3] - bbox[1]
# 定位
margin = 20
if position == "右下角":
x = img.width - text_w - margin
y = img.height - text_h - margin
elif position == "左下角":
x = margin
y = img.height - text_h - margin
elif position == "居中":
x = (img.width - text_w) // 2
y = (img.height - text_h) // 2
# 绘制半透明文字
draw.text((x, y), text, font=font, fill=(255, 255, 255, 100))
# 合并
result = Image.alpha_composite(img, watermark)
result = result.convert("RGB")
output_path = os.path.join(self.output_dir, f"wm_{f}")
result.save(output_path, quality=95)
print(f"已添加水印: {f}")
def create_collage(self, photos_per_row=3):
"""
创建照片拼图(适合发朋友圈九宫格预览)
"""
photos = [f for f in os.listdir(self.input_dir)
if f.lower().endswith((".jpg", ".jpeg", ".png"))]
if not photos:
return
# 设定每张小图尺寸
thumb_size = 300
rows = (len(photos) + photos_per_row - 1) // photos_per_row
canvas = Image.new("RGB",
(photos_per_row * thumb_size, rows * thumb_size),
(255, 255, 255) # 白色背景
)
for i, f in enumerate(photos):
img = Image.open(os.path.join(self.input_dir, f))
img.thumbnail((thumb_size - 10, thumb_size - 10))
x = (i % photos_per_row) * thumb_size + 5
y = (i // photos_per_row) * thumb_size + 5
canvas.paste(img, (x, y))
output_path = os.path.join(self.output_dir, "collage.jpg")
canvas.save(output_path, quality=95)
print(f"拼图已生成: {output_path}")
# 使用
processor = PhotoProcessor("原始照片", "输出照片")
processor.resize_for_wechat(max_width=1080)
# processor.add_watermark("张政 & 爱妻")
# processor.create_collage(photos_per_row=3)
四、其他常用场景
1. 批量格式转换
python
def batch_convert(input_dir, output_dir, target_format="png"):
"""批量转换图片格式"""
os.makedirs(output_dir, exist_ok=True)
for f in os.listdir(input_dir):
name, ext = os.path.splitext(f)
if ext.lower() not in (".jpg", ".jpeg", ".png", ".bmp", ".webp"):
continue
img = Image.open(os.path.join(input_dir, f))
output_path = os.path.join(output_dir, f"{name}.{target_format}")
img.save(output_path)
print(f"已转换: {f} → {output_path}")
# 把所有 jpg 转成 png
batch_convert("原始图片", "输出图片", "png")
2. 图片压缩
python
def compress_images(input_dir, output_dir, quality=60):
"""批量压缩图片(适合上传到网站)"""
os.makedirs(output_dir, exist_ok=True)
for f in os.listdir(input_dir):
if not f.lower().endswith((".jpg", ".jpeg", ".png")):
continue
img = Image.open(os.path.join(input_dir, f))
output_path = os.path.join(output_dir, f"compressed_{f}")
img.save(output_path, quality=quality, optimize=True)
original_size = os.path.getsize(os.path.join(input_dir, f))
compressed_size = os.path.getsize(output_path)
ratio = (1 - compressed_size / original_size) * 100
print(f"{f}: {original_size//1024}KB → {compressed_size//1024}KB (压缩 {ratio:.0f}%)")
# 压缩到 60% 质量
compress_images("原始图片", "压缩图片", quality=60)
3. 添加滤镜效果
python
def apply_filters():
img = Image.open("照片.jpg")
# 各种滤镜效果
img.filter(ImageFilter.BLUR) # 模糊
img.filter(ImageFilter.CONTOUR) # 轮廓
img.filter(ImageFilter.EMBOSS) # 浮雕
img.filter(ImageFilter.SHARPEN) # 锐化
img.filter(ImageFilter.SMOOTH) # 平滑
# 转换为灰度
gray = img.convert("L")
# 增强亮度/对比度
from PIL import ImageEnhance
enhancer = ImageEnhance.Brightness(img)
brighter = enhancer.enhance(1.3) # 亮度增加 30%
enhancer = ImageEnhance.Contrast(img)
higher_contrast = enhancer.enhance(1.2)
4. 批量重命名
python
import os
def batch_rename(directory, prefix="IMG_", start=1):
"""批量重命名图片"""
files = [f for f in os.listdir(directory)
if f.lower().endswith((".jpg", ".jpeg", ".png", ".webp"))]
files.sort()
for i, f in enumerate(files):
ext = os.path.splitext(f)[1]
new_name = f"{prefix}{start + i:03d}{ext}"
os.rename(
os.path.join(directory, f),
os.path.join(directory, new_name)
)
print(f"{f} → {new_name}")
# 使用:重命名为 IMG_001.jpg, IMG_002.jpg ...
batch_rename("婚纱照原片", prefix="wedding_", start=1)
五、实际工作流
① 从相机/手机导出照片 → ② 批量重命名
③ 批量调整尺寸/压缩 → ④ 添加水印
⑤ 挑选部分做滤镜/拼图 → ⑥ 发朋友圈/上传
每一步都写成一个函数,中间环节不满意就调整参数重新运行,不用一张一张手动处理。
六、常见问题
1. OSError: cannot identify image file
python
# 原因:文件扩展名和实际格式不一致
# 解决:用 try 跳过损坏的图片
try:
img = Image.open(file)
img.verify() # 验证图片是否损坏
except:
print(f"跳过损坏文件: {file}")
2. 中文文字显示为方框
python
# 原因:Pillow 默认字体不支持中文
# 解决:指定中文字体
font = ImageFont.truetype("C:/Windows/Fonts/simhei.ttf", 36)
# 常见的 Windows 中文字体路径:
# 微软雅黑: msyh.ttc
# 宋体: simsun.ttc
# 黑体: simhei.ttf
3. 图片太大导致内存不足
python
# 处理超大图片时,先缩小再操作
img = Image.open("超大图片.jpg")
img.thumbnail((4000, 4000)) # 限制最长边 4000 像素
总结
Pillow 几乎可以搞定日常所有的图片处理需求。把常用的几个功能写成脚本,下次处理图片时直接运行就行,比一张张手动操作省下 90% 的时间。
最常用的三个场景:
- 批量改尺寸(发朋友圈/上传网站)
- 批量加水印(保护版权)
- 批量压缩(节省空间)
💡 觉得有用的话,点赞 + 关注【张老师技术栈】吧!每周更新 Java/Python/爬虫 实战干货,不让你白来。