1. 什么是 Pillow #
Pillow 是 Python 中最流行的图像处理库,它是 PIL(Python Imaging Library)的现代维护版本。
为什么选择 Pillow?
- 功能强大:支持几乎所有常见的图像格式
- 易于使用:API 简洁直观
- 广泛应用:在 Web 开发、数据分析、机器学习等领域都有大量使用
- 性能优秀:底层使用 C 语言实现,处理速度快
Pillow 能做什么?
- 打开、保存各种格式的图片
- 调整图片大小、旋转、翻转
- 裁剪、拼接图片
- 添加滤镜效果
- 调整亮度、对比度、饱和度
- 在图片上绘制图形和文字
- 批量处理多张图片
2. 安装 Pillow #
在使用 Pillow 之前,需要先安装它。安装方法非常简单:
# 使用 pip 安装(推荐)
pip install Pillow
# 如果使用 conda
conda install pillow验证安装: 安装完成后,可以在 Python 中导入来验证是否安装成功:
# 导入 Pillow 库
# 注意:虽然安装的是 Pillow,但导入时使用 PIL(保持向后兼容)
from PIL import Image
# 如果导入成功,说明安装正确
print("Pillow 安装成功!")3. 图像打开与保存 #
打开和保存图像是 Pillow 最基础的操作,也是所有图像处理的第一步。
3.1 打开图像 #
使用 Image.open() 方法可以打开一张图片。这个方法支持多种格式:JPEG、PNG、GIF、BMP、TIFF、WebP 等。
# 导入 Image 模块
from PIL import Image
# 打开一张图片
# 参数:图片文件的路径(可以是相对路径或绝对路径)
img = Image.open('image.jpg')
# 如果图片不存在,会抛出 FileNotFoundError 异常
# 建议使用 try-except 处理异常
try:
img = Image.open('image.jpg')
print("图片打开成功!")
except FileNotFoundError:
print("图片文件不存在!")注意事项:
- 文件路径可以是相对路径(相对于当前工作目录)或绝对路径
- 打开图片后,图片数据并没有完全加载到内存,只有在需要时才会加载
- 打开后的图片对象可以查看基本信息,但修改操作会创建新的图片对象
3.2 保存图像 #
使用 save() 方法可以保存图片。Pillow 会根据文件扩展名自动选择保存格式。
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('input.jpg')
# 保存图片
# 方法1:使用默认格式(根据扩展名自动判断)
img.save('output.png') # 保存为 PNG 格式
# 方法2:显式指定格式
img.save('output.png', 'PNG')
# 方法3:保存时指定质量参数(适用于 JPEG)
img.save('output.jpg', 'JPEG', quality=85) # quality 范围 1-100,数值越大质量越好
# 方法4:保存为 WebP 格式(现代格式,压缩率高)
img.save('output.webp', 'WEBP', quality=85)完整示例:
# 导入 Image 模块
from PIL import Image
# 打开一张图片
img = Image.open('photo.jpg')
# 保存为不同格式
img.save('photo_copy.jpg') # 保存为 JPEG
img.save('photo_copy.png') # 保存为 PNG
img.save('photo_copy.webp') # 保存为 WebP
print("图片保存完成!")4. 获取图像基本信息 #
在处理图片之前,通常需要先了解图片的基本信息,比如尺寸、格式、颜色模式等。
4.1 基本属性 #
图片对象有几个常用的属性可以获取基本信息:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 获取图片格式(如 JPEG、PNG 等)
print("图片格式:", img.format)
# 获取图片尺寸,返回元组 (宽度, 高度)
print("图片尺寸:", img.size)
print("图片宽度:", img.width)
print("图片高度:", img.height)
# 获取图片颜色模式
# 常见模式:RGB(彩色)、RGBA(带透明通道)、L(灰度)、1(黑白)
print("颜色模式:", img.mode)4.2 完整示例 #
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 打印所有基本信息
print("=" * 40)
print("图片基本信息")
print("=" * 40)
print(f"格式: {img.format}")
print(f"尺寸: {img.size[0]} x {img.size[1]} 像素")
print(f"宽度: {img.width} 像素")
print(f"高度: {img.height} 像素")
print(f"颜色模式: {img.mode}")
print("=" * 40)颜色模式说明:
- RGB:红绿蓝三色模式,最常见的彩色图片模式
- RGBA:在 RGB 基础上增加了透明通道(Alpha),PNG 图片常用
- L:灰度模式,只有亮度信息,没有颜色信息
- 1:二值图像,只有黑白两种颜色
- P:调色板模式,使用颜色索引表
5. 图像基本操作 #
图像的基本操作包括调整大小、旋转、翻转等,这些是最常用的图像处理功能。
5.1 调整图片大小 #
调整图片大小有两种方法:resize() 和 thumbnail()。
方法1:resize() - 可以改变宽高比
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 调整到指定尺寸(宽度, 高度)
# 注意:这会改变图片的宽高比,可能导致图片变形
resized = img.resize((300, 200))
resized.save('resized_300x200.jpg')
# 按比例缩小(缩小到原来的一半)
new_width = img.width // 2
new_height = img.height // 2
resized_half = img.resize((new_width, new_height))
resized_half.save('resized_half.jpg')
print("图片调整完成!")方法2:thumbnail() - 保持宽高比
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 创建缩略图
# thumbnail() 会保持宽高比,确保图片不会变形
# 参数是最大尺寸,图片会按比例缩小,但不会超过这个尺寸
img.thumbnail((300, 300)) # 最大宽度和高度都是 300 像素
# 注意:thumbnail() 会直接修改原图片对象,不会创建新对象
img.save('thumbnail_300x300.jpg')
print("缩略图创建完成!")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('photo.jpg')
print(f"原始尺寸: {img.size}")
# 方法1:使用 resize(可能变形)
resized = img.resize((400, 300))
resized.save('resized.jpg')
print(f"resize 后尺寸: {resized.size}")
# 方法2:使用 thumbnail(保持比例)
img_copy = Image.open('photo.jpg') # 重新打开,因为 thumbnail 会修改原图
img_copy.thumbnail((400, 300))
img_copy.save('thumbnail.jpg')
print(f"thumbnail 后尺寸: {img_copy.size}")5.2 旋转图片 #
使用 rotate() 方法可以旋转图片:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 旋转图片
# 参数1:旋转角度(正数逆时针,负数顺时针)
# 参数2:expand=True 表示扩大画布以容纳旋转后的图片,避免被裁剪
rotated_90 = img.rotate(90, expand=True)
rotated_90.save('rotated_90.jpg')
# 旋转 45 度
rotated_45 = img.rotate(45, expand=True)
rotated_45.save('rotated_45.jpg')
# 旋转 -90 度(顺时针 90 度)
rotated_minus_90 = img.rotate(-90, expand=True)
rotated_minus_90.save('rotated_minus_90.jpg')
print("图片旋转完成!")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('photo.jpg')
# 旋转不同角度
angles = [90, 180, 270]
for angle in angles:
rotated = img.rotate(angle, expand=True)
rotated.save(f'rotated_{angle}.jpg')
print(f"已保存旋转 {angle} 度的图片")
print("所有旋转操作完成!")5.3 翻转图片 #
使用 transpose() 方法可以翻转图片:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
# 水平翻转(左右镜像)
flipped_horizontal = img.transpose(Image.FLIP_LEFT_RIGHT)
flipped_horizontal.save('flipped_horizontal.jpg')
# 垂直翻转(上下镜像)
flipped_vertical = img.transpose(Image.FLIP_TOP_BOTTOM)
flipped_vertical.save('flipped_vertical.jpg')
print("图片翻转完成!")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('photo.jpg')
# 水平翻转
horizontal = img.transpose(Image.FLIP_LEFT_RIGHT)
horizontal.save('flipped_horizontal.jpg')
# 垂直翻转
vertical = img.transpose(Image.FLIP_TOP_BOTTOM)
vertical.save('flipped_vertical.jpg')
print("翻转操作完成!")6. 图像模式转换 #
不同的图片有不同的颜色模式,有时需要转换模式以满足处理需求。
6.1 常见模式转换 #
# 导入 Image 模块
from PIL import Image
# 打开彩色图片
img = Image.open('color_image.jpg')
print(f"原始模式: {img.mode}")
# 转换为灰度图
# 'L' 表示灰度模式(Luminance)
gray_img = img.convert('L')
gray_img.save('gray_image.jpg')
print(f"灰度模式: {gray_img.mode}")
# 转换为 RGB 模式(确保是 RGB)
rgb_img = img.convert('RGB')
rgb_img.save('rgb_image.jpg')
print(f"RGB 模式: {rgb_img.mode}")
# 转换为 RGBA 模式(添加透明通道)
rgba_img = img.convert('RGBA')
rgba_img.save('rgba_image.png') # PNG 支持透明通道
print(f"RGBA 模式: {rgba_img.mode}")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('photo.jpg')
print(f"原始图片模式: {img.mode}")
# 转换为灰度图
if img.mode != 'L':
gray = img.convert('L')
gray.save('photo_gray.jpg')
print(f"灰度图已保存,模式: {gray.mode}")
# 确保是 RGB 模式
if img.mode != 'RGB':
rgb = img.convert('RGB')
rgb.save('photo_rgb.jpg')
print(f"RGB 图已保存,模式: {rgb.mode}")模式转换说明:
- RGB → L(灰度):将彩色图片转为黑白,常用于简化处理
- 任意模式 → RGB:统一转换为 RGB,确保后续处理兼容
- RGB → RGBA:添加透明通道,用于需要透明效果的场景
7. 图像裁剪与合成 #
裁剪可以提取图片的某个区域,合成可以将多张图片组合在一起。
7.1 裁剪图片 #
使用 crop() 方法可以裁剪图片的指定区域:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('image.jpg')
print(f"原始尺寸: {img.size}")
# 裁剪图片
# crop() 的参数是一个元组:(左, 上, 右, 下)
# 坐标系统:左上角为 (0, 0),向右为 x 轴正方向,向下为 y 轴正方向
# 例如:(100, 100, 400, 400) 表示从 (100, 100) 到 (400, 400) 的矩形区域
box = (100, 100, 400, 400)
cropped = img.crop(box)
cropped.save('cropped.jpg')
print(f"裁剪后尺寸: {cropped.size}")
# 裁剪图片中心区域
width, height = img.size
# 计算中心区域的坐标
left = width // 4
top = height // 4
right = width * 3 // 4
bottom = height * 3 // 4
center_box = (left, top, right, bottom)
center_cropped = img.crop(center_box)
center_cropped.save('center_cropped.jpg')
print("裁剪完成!")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开图片
img = Image.open('photo.jpg')
width, height = img.size
print(f"原始图片尺寸: {width} x {height}")
# 裁剪左上角 1/4 区域
box1 = (0, 0, width // 2, height // 2)
cropped1 = img.crop(box1)
cropped1.save('cropped_top_left.jpg')
print(f"左上角区域: {cropped1.size}")
# 裁剪中心区域
left = width // 4
top = height // 4
right = width * 3 // 4
bottom = height * 3 // 4
box2 = (left, top, right, bottom)
cropped2 = img.crop(box2)
cropped2.save('cropped_center.jpg')
print(f"中心区域: {cropped2.size}")7.2 合成图片(粘贴) #
使用 paste() 方法可以将一张图片粘贴到另一张图片上:
# 导入 Image 模块
from PIL import Image
# 打开主图片
main_img = Image.open('background.jpg')
# 打开要粘贴的图片(如 logo)
logo = Image.open('logo.png')
# 调整 logo 大小(可选)
logo.thumbnail((100, 100))
# 粘贴图片
# 参数1:要粘贴的图片
# 参数2:粘贴位置的坐标 (x, y),左上角为 (0, 0)
main_img.paste(logo, (50, 50))
# 保存结果
main_img.save('pasted.jpg')
print("图片粘贴完成!")完整示例:
# 导入 Image 模块
from PIL import Image
# 打开背景图片
background = Image.open('background.jpg')
print(f"背景图片尺寸: {background.size}")
# 打开要粘贴的图片
overlay = Image.open('logo.png')
print(f"原 logo 尺寸: {overlay.size}")
# 调整 logo 大小
overlay.thumbnail((200, 200))
print(f"调整后 logo 尺寸: {overlay.size}")
# 粘贴到不同位置
# 左上角
background_copy1 = background.copy()
background_copy1.paste(overlay, (10, 10))
background_copy1.save('pasted_top_left.jpg')
# 右下角
background_copy2 = background.copy()
x = background.width - overlay.width - 10
y = background.height - overlay.height - 10
background_copy2.paste(overlay, (x, y))
background_copy2.save('pasted_bottom_right.jpg')
print("粘贴操作完成!")8. 滤镜与图像增强 #
Pillow 提供了丰富的滤镜效果和图像增强功能,可以让图片看起来更好。
8.1 应用滤镜 #
使用 ImageFilter 模块可以应用各种滤镜效果:
# 导入需要的模块
from PIL import Image, ImageFilter
# 打开图片
img = Image.open('image.jpg')
# 模糊效果
blurred = img.filter(ImageFilter.BLUR)
blurred.save('blurred.jpg')
# 锐化效果
sharpened = img.filter(ImageFilter.SHARPEN)
sharpened.save('sharpened.jpg')
# 边缘检测
edges = img.filter(ImageFilter.FIND_EDGES)
edges.save('edges.jpg')
# 轮廓效果
contour = img.filter(ImageFilter.CONTOUR)
contour.save('contour.jpg')
# 浮雕效果
emboss = img.filter(ImageFilter.EMBOSS)
emboss.save('emboss.jpg')
print("滤镜应用完成!")完整示例:
# 导入需要的模块
from PIL import Image, ImageFilter
# 打开图片
img = Image.open('photo.jpg')
# 定义要应用的滤镜
filters = {
'blur': ImageFilter.BLUR,
'sharpen': ImageFilter.SHARPEN,
'edges': ImageFilter.FIND_EDGES,
'contour': ImageFilter.CONTOUR,
'emboss': ImageFilter.EMBOSS,
}
# 应用每个滤镜并保存
for name, filter_type in filters.items():
filtered = img.filter(filter_type)
filtered.save(f'filtered_{name}.jpg')
print(f"已保存 {name} 滤镜效果")
print("所有滤镜应用完成!")8.2 图像增强 #
使用 ImageEnhance 模块可以调整图片的亮度、对比度、饱和度等:
# 导入需要的模块
from PIL import Image, ImageEnhance
# 打开图片
img = Image.open('image.jpg')
# 调整亮度
# 创建亮度增强器
brightness_enhancer = ImageEnhance.Brightness(img)
# enhance() 参数:1.0 为原始亮度,>1.0 更亮,<1.0 更暗
bright_img = brightness_enhancer.enhance(1.5) # 提高 50% 亮度
bright_img.save('bright.jpg')
# 调整对比度
contrast_enhancer = ImageEnhance.Contrast(img)
# enhance() 参数:1.0 为原始对比度,>1.0 对比度更高,<1.0 对比度更低
high_contrast = contrast_enhancer.enhance(2.0) # 对比度加倍
high_contrast.save('high_contrast.jpg')
# 调整色彩饱和度
color_enhancer = ImageEnhance.Color(img)
# enhance() 参数:1.0 为原始饱和度,>1.0 更鲜艳,<1.0 更灰暗
vibrant = color_enhancer.enhance(1.5) # 饱和度提高 50%
vibrant.save('vibrant.jpg')
# 调整清晰度
sharpness_enhancer = ImageEnhance.Sharpness(img)
# enhance() 参数:1.0 为原始清晰度,>1.0 更清晰,<1.0 更模糊
sharp = sharpness_enhancer.enhance(2.0) # 清晰度加倍
sharp.save('sharp.jpg')
print("图像增强完成!")完整示例:
# 导入需要的模块
from PIL import Image, ImageEnhance
# 打开图片
img = Image.open('photo.jpg')
# 调整亮度
brightness = ImageEnhance.Brightness(img)
bright = brightness.enhance(1.3) # 提高 30% 亮度
bright.save('enhanced_bright.jpg')
# 调整对比度
contrast = ImageEnhance.Contrast(img)
high_contrast = contrast.enhance(1.5) # 提高 50% 对比度
high_contrast.save('enhanced_contrast.jpg')
# 调整饱和度
color = ImageEnhance.Color(img)
vibrant = color.enhance(1.4) # 提高 40% 饱和度
vibrant.save('enhanced_color.jpg')
print("所有增强操作完成!")9.绘制图形和文字 #
Pillow 可以在图片上绘制图形和文字,这对于添加水印、标注等非常有用。
9.1 绘制图形 #
使用 ImageDraw 模块可以在图片上绘制各种图形:
# 导入需要的模块
from PIL import Image, ImageDraw
# 打开图片或创建新图片
img = Image.open('image.jpg')
# 创建绘制对象
draw = ImageDraw.Draw(img)
# 绘制矩形
# 参数:[(左上角x, 左上角y), (右下角x, 右下角y)], fill=填充颜色, outline=边框颜色
draw.rectangle([(100, 100), (200, 200)], fill='red', outline='blue', width=3)
# 绘制椭圆(圆形)
# 参数:[(左上角x, 左上角y), (右下角x, 右下角y)], fill=填充颜色
draw.ellipse([(150, 150), (250, 250)], fill='green', outline='black', width=2)
# 绘制直线
# 参数:[(起点x, 起点y), (终点x, 终点y)], fill=颜色, width=线宽
draw.line([(0, 0), (100, 100)], fill='yellow', width=5)
# 保存图片
img.save('drawn.jpg')
print("图形绘制完成!")完整示例:
# 导入需要的模块
from PIL import Image, ImageDraw
# 创建一个新的图片(白色背景)
img = Image.new('RGB', (500, 500), color='white')
# 创建绘制对象
draw = ImageDraw.Draw(img)
# 绘制矩形
draw.rectangle([(50, 50), (200, 150)], fill='red', outline='blue', width=3)
# 绘制圆形
draw.ellipse([(250, 50), (400, 200)], fill='green', outline='black', width=2)
# 绘制直线
draw.line([(50, 250), (450, 250)], fill='blue', width=5)
# 绘制多条线(折线)
points = [(100, 300), (200, 350), (300, 320), (400, 380)]
draw.line(points, fill='purple', width=3)
# 保存图片
img.save('drawn_shapes.jpg')
print("图形绘制完成!")9.2 添加文字 #
使用 ImageDraw 和 ImageFont 可以在图片上添加文字:
# 导入需要的模块
from PIL import Image, ImageDraw, ImageFont
# 打开图片
img = Image.open('image.jpg')
# 创建绘制对象
draw = ImageDraw.Draw(img)
# 设置字体
# 方法1:使用系统字体(如果可用)
try:
# 尝试加载 TrueType 字体
font = ImageFont.truetype('arial.ttf', size=40)
except:
# 如果失败,使用默认字体
font = ImageFont.load_default()
# 添加文字
# 参数:位置坐标 (x, y), 文字内容, fill=文字颜色, font=字体对象
draw.text((50, 50), "Hello Pillow", fill='white', font=font)
# 保存图片
img.save('text_added.jpg')
print("文字添加完成!")完整示例:
# 导入需要的模块
from PIL import Image, ImageDraw, ImageFont
# 打开图片
img = Image.open('photo.jpg')
# 创建绘制对象
draw = ImageDraw.Draw(img)
# 尝试加载字体,失败则使用默认字体
try:
# Windows 系统常见字体路径
font = ImageFont.truetype('C:/Windows/Fonts/arial.ttf', size=50)
except:
try:
# Linux 系统常见字体路径
font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', size=50)
except:
# 使用默认字体
font = ImageFont.load_default()
print("使用默认字体")
# 添加文字
text = "Hello Pillow!"
# 计算文字位置(居中)
# 注意:textsize 方法在某些版本中可能不同,这里使用简化方式
text_x = 50
text_y = 50
draw.text((text_x, text_y), text, fill='white', font=font)
# 添加带背景的文字(绘制矩形背景)
text_bbox = draw.textbbox((text_x, text_y), text, font=font)
draw.rectangle(text_bbox, fill='black')
draw.text((text_x, text_y), text, fill='white', font=font)
# 保存图片
img.save('text_added.jpg')
print("文字添加完成!")10. 批量处理图片 #
在实际应用中,经常需要批量处理多张图片,比如批量调整大小、批量转换格式等。
10.1 批量调整大小 #
# 导入需要的模块
import os
from PIL import Image
# 设置输入和输出文件夹
input_folder = 'input_images/' # 输入文件夹
output_folder = 'output_images/' # 输出文件夹
# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)
# 遍历输入文件夹中的所有文件
for filename in os.listdir(input_folder):
# 检查文件扩展名,只处理图片文件
if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')):
# 构建完整的文件路径
input_path = os.path.join(input_folder, filename)
# 打开图片
img = Image.open(input_path)
# 创建缩略图(保持宽高比)
img.thumbnail((800, 800))
# 构建输出文件路径
output_path = os.path.join(output_folder, filename)
# 保存处理后的图片
img.save(output_path)
print(f"已处理: {filename}")
print("批量处理完成!")10.2 批量格式转换 #
# 导入需要的模块
import os
from PIL import Image
# 设置输入和输出文件夹
input_folder = 'input_images/'
output_folder = 'output_images/'
# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)
# 目标格式
target_format = 'PNG' # 可以改为 'JPEG', 'WEBP' 等
# 遍历输入文件夹
for filename in os.listdir(input_folder):
if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.gif')):
# 打开图片
input_path = os.path.join(input_folder, filename)
img = Image.open(input_path)
# 转换为 RGB 模式(某些格式需要)
if img.mode != 'RGB' and target_format == 'JPEG':
img = img.convert('RGB')
# 构建输出文件名(改变扩展名)
name_without_ext = os.path.splitext(filename)[0]
output_filename = f"{name_without_ext}.{target_format.lower()}"
output_path = os.path.join(output_folder, output_filename)
# 保存为指定格式
img.save(output_path, target_format)
print(f"已转换: {filename} -> {output_filename}")
print("批量转换完成!")10.3 完整批量处理示例 #
# 导入需要的模块
import os
from PIL import Image
def batch_process_images(input_folder, output_folder, max_size=(800, 800)):
"""
批量处理图片:调整大小并转换为统一格式
参数:
input_folder: 输入文件夹路径
output_folder: 输出文件夹路径
max_size: 最大尺寸元组 (宽度, 高度)
"""
# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)
# 支持的图片格式
supported_formats = ('.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp')
# 统计信息
processed_count = 0
error_count = 0
# 遍历输入文件夹
for filename in os.listdir(input_folder):
# 检查文件格式
if not filename.lower().endswith(supported_formats):
continue
try:
# 构建文件路径
input_path = os.path.join(input_folder, filename)
# 打开图片
img = Image.open(input_path)
# 转换为 RGB 模式(统一格式)
if img.mode != 'RGB':
img = img.convert('RGB')
# 创建缩略图
img.thumbnail(max_size, Image.Resampling.LANCZOS)
# 构建输出文件名(统一为 .jpg)
name_without_ext = os.path.splitext(filename)[0]
output_filename = f"{name_without_ext}.jpg"
output_path = os.path.join(output_folder, output_filename)
# 保存图片
img.save(output_path, 'JPEG', quality=85)
processed_count += 1
print(f"✓ 已处理: {filename}")
except Exception as e:
error_count += 1
print(f"✗ 处理失败: {filename} - {str(e)}")
# 打印统计信息
print("\n" + "=" * 40)
print(f"处理完成!")
print(f"成功: {processed_count} 张")
print(f"失败: {error_count} 张")
print("=" * 40)
# 使用示例
if __name__ == '__main__':
batch_process_images('input_images/', 'output_images/', max_size=(800, 800))11. 实用示例 #
下面是一些实际应用中常用的示例。
11.1 添加文字水印 #
# 导入需要的模块
from PIL import Image, ImageDraw, ImageFont
def add_text_watermark(input_path, output_path, watermark_text, position='center'):
"""
给图片添加文字水印
参数:
input_path: 输入图片路径
output_path: 输出图片路径
watermark_text: 水印文字
position: 水印位置 ('center', 'bottom_right', 'top_left' 等)
"""
# 打开原图
img = Image.open(input_path).convert('RGBA')
# 创建文字图层
txt_layer = Image.new('RGBA', img.size, (255, 255, 255, 0))
draw = ImageDraw.Draw(txt_layer)
# 设置字体
try:
font = ImageFont.truetype('arial.ttf', 40)
except:
font = ImageFont.load_default()
# 获取文字尺寸
bbox = draw.textbbox((0, 0), watermark_text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
# 计算文字位置
if position == 'center':
x = (img.width - text_width) // 2
y = (img.height - text_height) // 2
elif position == 'bottom_right':
x = img.width - text_width - 20
y = img.height - text_height - 20
elif position == 'top_left':
x = 20
y = 20
else:
x = 20
y = 20
# 绘制半透明文字
draw.text((x, y), watermark_text, font=font,
fill=(255, 255, 255, 128)) # 白色,50% 透明度
# 合并图层
watermarked = Image.alpha_composite(img, txt_layer)
# 保存(转换为 RGB 模式)
watermarked.convert('RGB').save(output_path, 'JPEG', quality=95)
print(f"水印添加完成: {output_path}")
# 使用示例
add_text_watermark('photo.jpg', 'watermarked.jpg', 'My Watermark', position='bottom_right')11.2 图片拼接 #
# 导入需要的模块
from PIL import Image
def concat_images_horizontally(image_paths, output_path):
"""
水平拼接多张图片
参数:
image_paths: 图片路径列表
output_path: 输出图片路径
"""
# 打开所有图片
images = [Image.open(path) for path in image_paths]
# 获取所有图片的宽度和高度
widths = [img.width for img in images]
heights = [img.height for img in images]
# 计算总宽度和最大高度
total_width = sum(widths)
max_height = max(heights)
# 创建新图片(白色背景)
new_img = Image.new('RGB', (total_width, max_height), 'white')
# 依次粘贴图片
x_offset = 0
for img in images:
# 如果图片高度小于最大高度,居中粘贴
y_offset = (max_height - img.height) // 2
new_img.paste(img, (x_offset, y_offset))
x_offset += img.width
# 保存
new_img.save(output_path)
print(f"图片拼接完成: {output_path}")
# 使用示例
image_list = ['image1.jpg', 'image2.jpg', 'image3.jpg']
concat_images_horizontally(image_list, 'concatenated.jpg')11.3 创建图片网格 #
# 导入需要的模块
from PIL import Image
import os
def create_image_grid(image_folder, output_path, grid_size=(3, 3), thumb_size=(200, 200)):
"""
创建图片网格(缩略图墙)
参数:
image_folder: 图片文件夹路径
output_path: 输出图片路径
grid_size: 网格大小 (列数, 行数)
thumb_size: 每个缩略图的大小
"""
# 获取所有图片文件
image_files = [f for f in os.listdir(image_folder)
if f.lower().endswith(('.jpg', '.jpeg', '.png', '.gif'))]
# 限制图片数量
max_images = grid_size[0] * grid_size[1]
image_files = image_files[:max_images]
# 加载并创建缩略图
thumbnails = []
for filename in image_files:
img_path = os.path.join(image_folder, filename)
img = Image.open(img_path)
img.thumbnail(thumb_size)
thumbnails.append(img)
# 计算网格尺寸
grid_width = grid_size[0] * thumb_size[0]
grid_height = grid_size[1] * thumb_size[1]
# 创建画布
grid_img = Image.new('RGB', (grid_width, grid_height), 'white')
# 粘贴缩略图
for i, thumb in enumerate(thumbnails):
# 计算位置
col = i % grid_size[0]
row = i // grid_size[0]
x = col * thumb_size[0]
y = row * thumb_size[1]
# 居中粘贴
x_offset = x + (thumb_size[0] - thumb.width) // 2
y_offset = y + (thumb_size[1] - thumb.height) // 2
grid_img.paste(thumb, (x_offset, y_offset))
# 保存
grid_img.save(output_path)
print(f"图片网格创建完成: {output_path}")
# 使用示例
create_image_grid('images/', 'grid.jpg', grid_size=(4, 4), thumb_size=(150, 150))12. 常见问题与最佳实践 #
12.1 常见问题 #
问题1:图片文件不存在
# 导入需要的模块
from PIL import Image
import os
# 检查文件是否存在
image_path = 'image.jpg'
if os.path.exists(image_path):
img = Image.open(image_path)
print("图片打开成功")
else:
print(f"错误:文件 {image_path} 不存在")问题2:保存时格式不支持
# 导入需要的模块
from PIL import Image
img = Image.open('image.jpg')
# 显式指定格式
try:
img.save('output.webp', 'WEBP')
print("保存成功")
except Exception as e:
print(f"保存失败: {e}")
# 如果 WebP 不支持,保存为 PNG
img.save('output.png', 'PNG')问题3:处理大图片内存不足
# 导入需要的模块
from PIL import Image
# 打开大图片时使用 with 语句
with Image.open('large_image.jpg') as img:
# 先缩小再处理
img.thumbnail((2000, 2000))
# 进行其他处理
img.save('processed.jpg')12.2 最佳实践 #
- 使用 with 语句管理资源
# 导入需要的模块
from PIL import Image
# 推荐:使用 with 语句
with Image.open('image.jpg') as img:
img.thumbnail((800, 800))
img.save('thumbnail.jpg')
# 图片资源会自动释放- 处理前检查图片信息
# 导入需要的模块
from PIL import Image
img = Image.open('image.jpg')
# 检查图片信息
print(f"格式: {img.format}")
print(f"尺寸: {img.size}")
print(f"模式: {img.mode}")
# 根据信息决定处理方式
if img.mode != 'RGB':
img = img.convert('RGB')- 批量处理时添加错误处理
# 导入需要的模块
import os
from PIL import Image
for filename in os.listdir('images/'):
try:
img = Image.open(f'images/{filename}')
img.thumbnail((800, 800))
img.save(f'output/{filename}')
print(f"✓ {filename}")
except Exception as e:
print(f"✗ {filename}: {e}")- 保存 JPEG 时指定质量
# 导入需要的模块
from PIL import Image
img = Image.open('image.png')
# 保存 JPEG 时指定质量(1-100,推荐 85-95)
img.save('output.jpg', 'JPEG', quality=90)- 使用 thumbnail 保持宽高比
# 导入需要的模块
from PIL import Image
img = Image.open('image.jpg')
# 推荐:使用 thumbnail 保持宽高比
img.thumbnail((800, 600)) # 不会变形
img.save('thumbnail.jpg')
# 不推荐:使用 resize 可能变形
# resized = img.resize((800, 600)) # 可能变形