本文目录导读:

我来介绍几种使用Pillow库给图片添加水印的方法:
安装Pillow
pip install Pillow
文字水印
基础文字水印
from PIL import Image, ImageDraw, ImageFont
def add_text_watermark(input_image_path, output_image_path, text="Watermark"):
# 打开图片
image = Image.open(input_image_path)
# 创建绘图对象
draw = ImageDraw.Draw(image)
# 获取图片尺寸
width, height = image.size
# 设置字体(如果系统中没有该字体,会自动使用默认字体)
try:
font = ImageFont.truetype("arial.ttf", 36)
except:
font = ImageFont.load_default()
# 计算文字位置(右下角)
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# 设置位置(右下角,留出10像素边距)
position = (width - text_width - 10, height - text_height - 10)
# 添加文字(白色,半透明)
draw.text(position, text, fill=(255, 255, 255, 128), font=font)
# 保存图片
image.save(output_image_path)
# 使用示例
add_text_watermark("input.jpg", "output_watermark.jpg", "My Watermark")
半透明文字水印
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
def add_transparent_text_watermark(input_path, output_path, text="Watermark"):
# 打开原图
original = Image.open(input_path).convert("RGBA")
# 创建透明层
watermark = Image.new("RGBA", original.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark)
# 设置字体
try:
font = ImageFont.truetype("arial.ttf", 50)
except:
font = ImageFont.load_default()
# 计算文字位置(中心)
width, height = original.size
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = (width - text_width) // 2
y = (height - text_height) // 2
# 添加半透明文字(RGBA,A=128表示50%透明度)
draw.text((x, y), text, fill=(255, 255, 255, 128), font=font)
# 合并原图和透明层
watermarked = Image.alpha_composite(original, watermark)
# 保存(转为RGB如果不需透明度)
watermarked = watermarked.convert("RGB")
watermarked.save(output_path)
add_transparent_text_watermark("input.jpg", "output_transparent.jpg", "水印")
图片水印
基础图片水印
from PIL import Image
def add_image_watermark(input_image_path, watermark_image_path, output_image_path, position="bottom-right"):
# 打开原图和水印图
original = Image.open(input_image_path)
watermark = Image.open(watermark_image_path)
# 调整水印大小(建议为原图的10%)
width, height = original.size
watermark_size = int(min(width, height) * 0.1)
watermark = watermark.resize((watermark_size, watermark_size), Image.Resampling.LANCZOS)
# 水印位置
if position == "bottom-right":
x = width - watermark.width - 10
y = height - watermark.height - 10
elif position == "bottom-left":
x = 10
y = height - watermark.height - 10
elif position == "top-right":
x = width - watermark.width - 10
y = 10
elif position == "top-left":
x = 10
y = 10
elif position == "center":
x = (width - watermark.width) // 2
y = (height - watermark.height) // 2
# 添加水印
if original.mode != "RGBA":
original = original.convert("RGBA")
if watermark.mode != "RGBA":
watermark = watermark.convert("RGBA")
# 粘贴水印
original.paste(watermark, (x, y), watermark)
# 保存
original = original.convert("RGB")
original.save(output_image_path)
# 使用示例
add_image_watermark("input.jpg", "logo.png", "output_logo.jpg", "bottom-right")
批量添加水印
import os
from PIL import Image, ImageDraw, ImageFont
def batch_add_watermark(folder_path, output_folder, text="水印"):
# 创建输出文件夹
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 获取所有图片文件
image_extensions = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
for filename in os.listdir(folder_path):
if any(filename.lower().endswith(ext) for ext in image_extensions):
input_path = os.path.join(folder_path, filename)
output_path = os.path.join(output_folder, f"watermarked_{filename}")
# 添加水印
add_text_watermark(input_path, output_path, text)
print(f"Processed: {filename}")
# 使用示例
batch_add_watermark("images/", "watermarked_images/", "Copyright 2024")
斜向水印(防篡改)
from PIL import Image, ImageDraw, ImageFont
import math
def add_diagonal_watermark(input_path, output_path, text="Confidential"):
image = Image.open(input_path).convert("RGBA")
width, height = image.size
# 创建透明层
watermark = Image.new("RGBA", image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark)
# 设置字体
font_size = int(min(width, height) * 0.05)
try:
font = ImageFont.truetype("arial.ttf", font_size)
except:
font = ImageFont.load_default()
# 计算对角线长度和角度
diagonal_length = int(math.sqrt(width**2 + height**2))
angle = math.degrees(math.atan2(height, width))
# 创建旋转后的文字
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
# 重复添加水印形成背景效果
for i in range(-diagonal_length, diagonal_length + 1, font_size * 3):
for j in range(-diagonal_length, diagonal_length + 1, font_size * 3):
draw.text((i, j), text, fill=(255, 255, 255, 50), font=font)
# 旋转水印
watermark = watermark.rotate(-angle, expand=0)
# 合并
watermarked = Image.alpha_composite(image, watermark)
watermarked = watermarked.convert("RGB")
watermarked.save(output_path)
# 使用示例
add_diagonal_watermark("input.jpg", "output_diagonal.jpg", "保密")
实用函数:带参数控制
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
class WatermarkAdder:
def __init__(self):
self.font_path = None
def add_watermark(self, image_path, output_path, text=None, image_watermark=None,
opacity=0.5, position="center", font_size=None):
"""
添加水印的通用函数
参数:
image_path: 原图路径
output_path: 输出路径
text: 文字水印内容
image_watermark: 图片水印路径
opacity: 透明度 (0-1)
position: 位置 (center, top-left, top-right, bottom-left, bottom-right)
font_size: 字体大小
"""
original = Image.open(image_path).convert("RGBA")
width, height = original.size
# 创建透明层
watermark = Image.new("RGBA", original.size, (0, 0, 0, 0))
if text:
# 文字水印
draw = ImageDraw.Draw(watermark)
# 设置字体大小
if font_size is None:
font_size = int(min(width, height) * 0.03)
try:
font = ImageFont.truetype("arial.ttf", font_size)
except:
font = ImageFont.load_default()
# 计算位置
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
positions = {
"center": ((width - text_width) // 2, (height - text_height) // 2),
"top-left": (10, 10),
"top-right": (width - text_width - 10, 10),
"bottom-left": (10, height - text_height - 10),
"bottom-right": (width - text_width - 10, height - text_height - 10)
}
pos = positions.get(position, positions["center"])
alpha = int(255 * opacity)
draw.text(pos, text, fill=(255, 255, 255, alpha), font=font)
elif image_watermark:
# 图片水印
wm_image = Image.open(image_watermark).convert("RGBA")
# 调整水印大小
wm_size = int(min(width, height) * 0.1)
wm_image = wm_image.resize((wm_size, wm_size), Image.Resampling.LANCZOS)
# 调整透明度
if opacity < 1.0:
alpha = wm_image.split()[3]
alpha = alpha.point(lambda x: x * opacity)
wm_image.putalpha(alpha)
# 计算位置
positions = {
"center": ((width - wm_image.width) // 2, (height - wm_image.height) // 2),
"top-left": (10, 10),
"top-right": (width - wm_image.width - 10, 10),
"bottom-left": (10, height - wm_image.height - 10),
"bottom-right": (width - wm_image.width - 10, height - wm_image.height - 10)
}
pos = positions.get(position, positions["bottom-right"])
watermark.paste(wm_image, pos, wm_image)
# 合并
result = Image.alpha_composite(original, watermark)
result = result.convert("RGB")
result.save(output_path)
# 使用示例
adder = WatermarkAdder()
# 文字水印
adder.add_watermark("input.jpg", "output1.jpg",
text="Copyright 2024",
opacity=0.6,
position="bottom-right")
# 图片水印
adder.add_watermark("input.jpg", "output2.jpg",
image_watermark="logo.png",
opacity=0.4,
position="center")
使用建议
- 水印位置:根据图片内容选择合适位置,通常是角落或中心
- 透明度:不要过低影响原图效果,不要过高容易被去除
- 字体选择:选择清晰易读的字体
- 批量处理:对大量图片使用循环处理
- 质量保持:保存时注意图片质量设置
这些方法基本覆盖了常见的水印添加需求,你可以根据具体场景选择合适的方法。