python给图片批量添加水印filestools模块

又很多添加水印的方法,如opencv模块、PIL模块但是感觉都较为复杂,filestools模块其本质上也是对ImageDraw.Draw.text()方法做了进一步的封装,让我们用起来更加的简便。

使用 filestools实现全图水印

/usr/local/bin/pip3 install filestools -i https://pypi.douban.com/simple/ # 安装

我们使用add_mark()方法可以生成数量较多的水印,该方法有8个参数,比较重要的有

  • mark:水印的内容
  • 水印样式包括color、size、opacity、space、angle:颜色、大小、不透明度、空间、角度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import os
from watermarker.marker import add_mark # 添加水印模块

def update_img(dir,water_name):
try:
if not dir and water_name:
print("文件夹地址或水印名称不能为空")
return
for img_name in os.listdir(dir):
add_mark(file=os.path.join(dir,img_name), out=os.getcwd(), mark=water_name, opacity=0.3, angle=30, space=70, size=30)
except FileNotFoundError and NotADirectoryError:
print("文件夹地址不正确")
return
if __name__ in '__main__':
update_img(dir="图片地址",water_name="水印名字")
1
2
3
4
5
6
7
8
9
函数名称:add_mark,用于实现添加水印。
file:原始照片;
mark:使用哪些字符作为水印;
out:添加水印后保存的位置;
color:水印字体的颜色,默认颜色#8B8B1B;
size:水印字体的大小,默认50;
opacity:水印字体的透明度,默认0.15;
space:水印字体之间的间隔, 默认75个空格;
angle:水印字体的旋转角度,默认30度;

全局搜索并附加水印

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os,shutil,glob
from watermarker.marker import add_mark # 添加水印模块

def update_img(dir,water_name):

if not dir and water_name:
print("文件夹地址或水印名称不能为空")
return
for img_name_dir in dir: # 此时dir是个一个可编历对象
add_mark(file=img_name_dir, out=os.getcwd(), mark=water_name, opacity=0.3, angle=30, space=70, size=30)
img_name=str(img_name_dir).split("/")[-1]
shutil.move(img_name,img_name_dir)
print(img_name_dir,img_name)



if __name__ in '__main__':
for key in ['webp','png','jpg','jpeg']: # 对关键字
#获取一个可编历对象,使用它可以逐个获取匹配的文件路径名。glob.iglob与glob.glob()的区别是:glob.glob同时获取所有的匹配路径,而glob.iglob一次只获取一个匹配路径。
image_list=glob.iglob(f"/Users/jerry/source/**/*.{key}",recursive=True)
update_img(dir=image_list,water_name="jerryWang")

使用 Pillow实现右下角水印

如果你还没有安装 Pillow,可以通过 pip 安装:python.exe -m pip install pillow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import os
import glob
from PIL import Image, ImageDraw, ImageFont

def ensure_directory(directory):
"""
确保指定的目录存在,如果不存在则创建。
:param directory: 要确保存在的目录路径。
"""
if not os.path.exists(directory):
os.makedirs(directory)

def calculate_font_size(image_width):
"""
根据图像宽度计算字体大小。
:param image_width: 图像的宽度。
:return: 字体大小。
"""
# 这里可以自定义你的逻辑,以下只是一个示例:
return int(image_width / 20) # 假设每20像素对应一个字号单位

def add_watermark(image_path, watermark_text, output_dir):
# 打开原始图片
image = Image.open(image_path).convert("RGBA")
txt_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))

# 根据图片宽度计算字体大小
font_size = calculate_font_size(image.width)

try:
font = ImageFont.truetype("arial.ttf", size=font_size) # 尝试使用指定字体和计算出的字体大小
except IOError:
font = ImageFont.load_default() # 如果找不到指定的字体文件,使用默认字体

draw = ImageDraw.Draw(txt_layer)

lines = watermark_text.split("\n")
total_height = 0
max_width = 0

# 预先计算每行文本的尺寸
for line in lines:
bbox = draw.textbbox((0, 0), line, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
total_height += text_height
max_width = max(max_width, text_width)

# 计算右下角位置
width, height = image.size
margin = 10 # 边距
x = width - max_width - margin
y = height - total_height - margin

# 定义水印颜色和透明度
watermark_color = (125, 38, 205, 128) # RGBA颜色:紫色,透明度为128(半透明)

# 添加水印
for i, line in enumerate(lines):
bbox = draw.textbbox((0, 0), line, font=font)
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]
draw.text((x + (max_width - text_width), y + i * text_height - 30), line, font=font, fill=watermark_color)

# 合并原始图片和水印层
combined = Image.alpha_composite(image, txt_layer)

# 转换回RGB模式以便保存为常见格式
combined = combined.convert("RGB")

# 生成输出路径
filename = os.path.basename(image_path)
output_path = os.path.join(output_dir, filename)

# 保存图片
combined.save(output_path)
print(f"Processed and saved {output_path}")

def update_img(dir, water_name, output_dir):
ensure_directory(output_dir) # 确保输出目录存在
for img_name_dir in dir: # 此时dir是一个可迭代对象
add_watermark(img_name_dir, water_name, output_dir)

if __name__ == '__main__':
script_dir = os.getcwd() # 获取脚本所在目录
output_dir = os.path.join(script_dir, "shuiyin_img") # 输出目录为脚本目录下的'shuiyin_img'子目录

for key in ['webp', 'png', 'jpg', 'jpeg']: # 对关键字
# 使用glob.iglob函数获取指定目录下所有指定扩展名的文件路径,并将其存储在image_list变量中
image_list = glob.iglob(rf"C:\newBlog\新建文件夹\*.{key}", recursive=True)
update_img(dir=image_list, water_name="jerryWang", output_dir=output_dir) # 确保image_list被转换成列表

代码解释

  1. 导入必要的库:包括 os, shutil, globPillow
  2. 定义 add_watermark 函数:
    • 打开原始图片并创建一个新的透明图层用于绘制水印。
    • 使用 ImageFont 设置字体和大小。
    • 计算水印文本的尺寸,并确定其在右下角的位置。
    • 使用 ImageDraw.Draw 在透明图层上绘制水印。
    • 将透明图层与原始图片合并,并保存结果到指定目录。
  3. 定义 update_img 函数:
    • 遍历传入的图片列表,并调用 add_watermark 函数为每张图片添加水印。
  4. 主程序入口:
    • 使用 glob.iglob 查找所有符合条件的图片文件,并调用 update_img 处理它们。