本文目录导读:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
批量图片水印添加脚本
功能:为指定文件夹内所有图片添加文字水印,并支持灵活调整水印位置
依赖:Pillow (pip install Pillow)
"""
import os
import argparse
from PIL import Image, ImageDraw, ImageFont
# 水印位置预设
POSITIONS = {
'左上': (0.05, 0.05),
'右上': (0.85, 0.05),
'左下': (0.05, 0.85),
'右下': (0.85, 0.85),
'居中': (0.40, 0.45),
}
def get_font(size, font_path=None):
"""加载字体,若未提供则使用默认字体"""
try:
if font_path and os.path.exists(font_path):
return ImageFont.truetype(font_path, size)
# 尝试加载常见中文字体,否则用默认
for candidate in [
"msyh.ttc", "simhei.ttf", "arial.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
]:
try:
return ImageFont.truetype(candidate, size)
except:
continue
return ImageFont.load_default()
except:
return ImageFont.load_default()
def add_watermark(input_path, output_path, text, position='右下',
font_size=24, opacity=128, font_path=None,
margin=10, angle=0):
"""
为单张图片添加水印
参数:
input_path: 输入图片路径
output_path: 输出图片路径
text: 水印文字内容
position: 水印位置(左上/右上/左下/右下/居中,或自定义坐标元组)
font_size: 字体大小
opacity: 透明度 (0-255)
font_path: 字体文件路径(可选)
margin: 边距(像素)
angle: 水印旋转角度(度)
"""
try:
# 打开图片并转换为RGBA模式以支持透明
image = Image.open(input_path).convert('RGBA')
img_width, img_height = image.size
# 创建透明水印层
watermark = Image.new('RGBA', image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark)
# 获取字体
font = get_font(font_size, font_path)
# 计算文字尺寸
try:
bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
except:
text_width, text_height = draw.textsize(text, font=font)
# 确定水印位置
if isinstance(position, tuple):
# 自定义坐标(相对位置 0-1)
x = int((img_width - text_width) * position[0])
y = int((img_height - text_height) * position[1])
elif position in POSITIONS:
# 预设位置
rel_x, rel_y = POSITIONS[position]
# 预设位置默认带边距
x = int((img_width - text_width) * rel_x)
y = int((img_height - text_height) * rel_y)
else:
raise ValueError(f"未知位置: {position}")
# 应用边距
x = max(0, min(x + margin, img_width - text_width - margin))
y = max(0, min(y + margin, img_height - text_height - margin))
# 添加文字到水印层
draw.text((x, y), text, font=font, fill=(255, 255, 255, opacity))
# 如果需要旋转
if angle != 0:
watermark = watermark.rotate(angle, resample=Image.BICUBIC,
center=(x + text_width//2, y + text_height//2))
# 合并原图和水印
result = Image.alpha_composite(image, watermark)
# 转换为RGB模式保存(去除alpha通道)
if output_path.lower().endswith('.jpg') or output_path.lower().endswith('.jpeg'):
result = result.convert('RGB')
result.save(output_path)
print(f"✅ 已处理: {os.path.basename(input_path)} -> {output_path}")
return True
except Exception as e:
print(f"❌ 处理失败 {os.path.basename(input_path)}: {str(e)}")
return False
def batch_watermark(input_dir, output_dir, text, **kwargs):
"""批量处理指定目录下的所有图片"""
# 支持的图片格式
img_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff'}
# 创建输出目录
os.makedirs(output_dir, exist_ok=True)
# 收集所有图片文件
img_files = [f for f in os.listdir(input_dir)
if os.path.splitext(f)[1].lower() in img_extensions]
if not img_files:
print("⚠️ 未找到任何图片文件")
return
print(f"📁 找到 {len(img_files)} 张图片,开始处理...")
success_count = 0
for filename in sorted(img_files):
input_path = os.path.join(input_dir, filename)
# 保持原文件名,但更改扩展号为.png(支持透明)
output_filename = os.path.splitext(filename)[0] + '_watermarked.png'
output_path = os.path.join(output_dir, output_filename)
if add_watermark(input_path, output_path, text, **kwargs):
success_count += 1
print(f"\n🎉 处理完成!成功: {success_count}/{len(img_files)} 张图片")
print(f"📂 输出目录: {os.path.abspath(output_dir)}")
def main():
parser = argparse.ArgumentParser(description='批量图片水印添加工具')
parser.add_argument('input_dir', help='输入图片目录路径')
parser.add_argument('output_dir', help='输出图片目录路径')
parser.add_argument('--text', required=True, help='水印文字内容')
parser.add_argument('--position', default='右下',
choices=list(POSITIONS.keys()),
help='水印位置:左上/右上/左下/右下/居中 (默认: 右下)')
parser.add_argument('--font-size', type=int, default=24, help='字体大小 (默认: 24)')
parser.add_argument('--opacity', type=int, default=128,
help='透明度 0-255 (默认: 128)')
parser.add_argument('--font-path', help='字体文件路径(可选)')
parser.add_argument('--margin', type=int, default=10, help='边距像素 (默认: 10)')
parser.add_argument('--angle', type=float, default=0, help='旋转角度(度)')
args = parser.parse_args()
# 参数校验
if not 0 <= args.opacity <= 255:
print("⚠️ 透明度必须在 0-255 之间,已自动处理")
args.opacity = max(0, min(255, args.opacity))
batch_watermark(
args.input_dir,
args.output_dir,
args.text,
position=args.position,
font_size=args.font_size,
opacity=args.opacity,
font_path=args.font_path,
margin=args.margin,
angle=args.angle
)
if __name__ == '__main__':
main()
使用方法
安装依赖
pip install Pillow
命令行用法示例
# 基本用法(默认右下角水印) python watermark.py ./input_images ./output_images --text "© 我的水印" # 指定位置为居中 python watermark.py ./input_images ./output_images --text "机密" --position 居中 # 自定义字体大小和透明度 python watermark.py ./input ./output --text "保密" --position 右上 --font-size 36 --opacity 150 # 使用指定字体文件 python watermark.py ./input ./output --text "设计师" --position 左下 --font-path "C:/Windows/Fonts/msyh.ttc" # 添加旋转效果 python watermark.py ./input ./output --text "预览版" --position 居中 --angle 30
在Python代码中调用
from watermark import batch_watermark
# 批量处理
batch_watermark(
input_dir="photos",
output_dir="watermarked",
text="© 2024",
position="右下",
font_size=30,
opacity=150,
margin=15
)
脚本特性
- 多位置预设:支持左上、右上、左下、右下、居中五种常用位置
- 自定义坐标:可传入精确的相对坐标 (0~1之间的浮点数)
- 参数丰富:可调节字体大小、透明度、边距和旋转角度
- 自动编码处理:自动读取图片并保持格式,输出为PNG以支持透明
- 批量处理:自动遍历目录内所有常见图片格式
- 错误处理:单个文件失败不影响其他文件处理
注意事项
- 输出的图片格式统一为PNG,以支持高质量的透明效果
- 若需要保持原始格式(如JPG),可以修改脚本中的保存部分代码
- 中文水印需要系统有中文字体支持,否则会显示方块
- 建议先在小规模测试,确认效果后再批量处理
如果您需要调整水印样式(如添加阴影、边框等),可以告诉我,我可以进一步扩展脚本功能。