本文目录导读:

#!/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),可以修改脚本中的保存部分代码
- 中文水印需要系统有中文字体支持,否则会显示方块
- 建议先在小规模测试,确认效果后再批量处理
如果您需要调整水印样式(如添加阴影、边框等),可以告诉我,我可以进一步扩展脚本功能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播