首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 批量自动化给图片添加水印

Python 批量自动化给图片添加水印

作者头像
用户11081884
发布2026-07-20 16:52:50
发布2026-07-20 16:52:50
150
举报

Python在图像处理领域有强大的能力和灵活性,无论是简单的文字水印还是复杂的透明图层混合,都能轻松实现。第三方库如filestools更是将复杂的水印效果简化为一行代码,大大提高了开发效率。本文将全面介绍如何使用Python实现图片水印的批量自动化添加,涵盖基础的Pillow库操作和高级的filestools工具应用,帮助高效完成图片添加水印工作。

一、安装库:

Pillow库是Python图像处理的标准库,能够处理多种图片格式,支持打开、操作和保存各种图像文件。filestools是第三方库,其中的watermarker模块可以用一行代码就实现水印效果。

代码语言:javascript
复制
pip install pillow  # 基础图像处理库
pip install filestools -U  # 高级水印工具库

导入模块:

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont
import os
from watermarker.marker import add_mark  

二、单张图片添加水印

方法一:直接在原图上绘制文本水印

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont
import os
from watermarker.marker import add_mark  

image = Image.open(r'E:\learn\gzh\image-20250703172759851.png')
# 创建绘图对象
draw = ImageDraw.Draw(image)
# 设置字体(Windows系统可以使用simhei.ttf支持中文)
font = ImageFont.truetype('simhei.ttf', 36)  # 或者使用'simhei.ttf'
# 设置水印文字颜色(RGB格式)
text_color = (0, 255, 0) 
# 在图片右下角添加水印
width, height = image.size
draw.text((width - 450, height - 150), "Nicholas与Pypi", fill=text_color, font=font)
# 将图像模式从 RGBA 转换为 RGB
image = image.convert('RGB')
# 保存图片
image.save(r'E:\learn\gzh\watermarked_test.jpg')

注意事项:

  • 字体文件路径需要根据系统实际情况调整;
  • 水印位置(x,y)坐标可以根据需要修改;
  • 中文水印需要使用支持中文的字体文件;

方法二:使用透明图层添加水印

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont
import os
from watermarker.marker import add_mark

# 打开原始图片并转换为RGBA模式
image = Image.open(r'E:\learn\gzh\watermarked_test.jpg').convert('RGBA')
# 创建透明图层
watermark_layer = Image.new('RGBA', image.size, (0, 0, 0, 0))
# 在透明图层上绘制水印
draw = ImageDraw.Draw(watermark_layer)
# 设置字体(确保字体文件路径正确)
font = ImageFont.truetype('simhei.ttf', 36)
text_color = (255, 255, 255, 128)  # 白色,50%透明度
width, height = image.size
text = "Nicholas与Pypi"
# 计算文字尺寸
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
draw.text((x, y), text, fill=text_color, font=font)
# 合并图层
combined_image = Image.alpha_composite(image, watermark_layer)
# 保存图片(转换为RGB模式以兼容JPEG格式)
combined_image.convert('RGB').save(r'E:\learn\gzh\watermarked_test1.jpg')

这种方法可以实现更灵活的水印效果,包括透明度控制、图层混合等高级功能。

三、批量图片添加水印

单张图片的水印添加后,可以扩展为批量处理,大大提高效率。

批量处理实现

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont
import os

def calculate_position(base_size, text_size, position='bottom-right'):
    """计算水印位置"""
    positions = {
        'top-left': (20, 20),
        'top-right': (base_size[0] - text_size[0] - 20, 20),
        'center': ((base_size[0] - text_size[0]) // 2, 
                  (base_size[1] - text_size[1]) // 2),
        'bottom-left': (20, base_size[1] - text_size[1] - 20),
        'bottom-right': (base_size[0] - text_size[0] - 20, 
                        base_size[1] - text_size[1] - 20)
    }
    return positions.get(position, (0, 0))

def adjust_opacity(color, opacity):
    """调整颜色透明度"""
    return (color[0], color[1], color[2], int(255 * opacity))

# 水印参数设置
watermark_text = "Nicholas与Pypi"
base_font_size = 36
text_color = (0, 255, 0)  # 绿色
opacity = 0.5  # 50%透明度
position = 'bottom-right'  # 水印位置

# 图片文件夹路径
image_folder = 'images'
output_folder = 'watermarked_images'

# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)

# 遍历文件夹中的所有文件
for filename in os.listdir(image_folder):
    # 检查文件扩展名
    if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
        # 打开图片
        image_path = os.path.join(image_folder, filename)
        image = Image.open(image_path).convert('RGBA')
        
        # 自适应字体大小
        font_size = int(min(image.size) * 0.05)
        font = ImageFont.truetype('simhei.ttf', font_size)
        
        # 创建透明图层
        txt_layer = Image.new('RGBA', image.size, (255, 255, 255, 0))
        draw = ImageDraw.Draw(txt_layer)
        
        # 计算水印位置
        bbox = draw.textbbox((0, 0), watermark_text, font=font)
        text_width = bbox[2] - bbox[0]
        text_height = bbox[3] - bbox[1]
        x, y = calculate_position(image.size, (text_width, text_height), position)
        
        # 调整透明度
        adjusted_color = adjust_opacity(text_color, opacity)
        
        # 绘制水印
        draw.text((x, y), watermark_text, font=font, fill=adjusted_color)
        
        # 合并图层并保存
        watermarked = Image.alpha_composite(image, txt_layer)
        output_path = os.path.join(output_folder, filename)
        watermarked.convert('RGB').save(output_path)
        
        print(f"已处理: {filename}")

功能说明:

  1. 水印位置自定义
    • 通过 calculate_position 函数,你可以轻松设置水印的位置,支持 top-lefttop-rightcenterbottom-leftbottom-right
  2. 水印透明度调节
    • 通过 adjust_opacity 函数,你可以调整水印的透明度,范围从 0(完全透明)到 1(完全不透明)。
  3. 自适应字体大小
    • 根据图片的大小自动调整字体大小,使水印在不同尺寸的图片上都能保持良好的可读性。

将代码中 image_folderoutput_folder 变量设置为你的图片文件夹路径和输出文件夹路径。根据需要调整 watermark_texttext_coloropacityposition 参数。运行代码后,所有处理后的图片将保存在 output_folder 中。

四、使用filestools库

filestools库提供的watermarker模块可以实现一行代码添加水印的强大功能,可以极大的提升效率和简便性。

单张图片水印添加

代码语言:javascript
复制
from watermarker.marker import add_mark

add_mark(file=r'E:\learn\gzh\image-20250703172759851.png', 
         out=r'E:\learn\gzh\watermarked_test2.jpg', 
         mark="Nicholas与Pypi", 
         opacity=0.3, 
         angle=30, 
         space=30, 
         size=50)

参数说明:

  • file: 原始图片路径;
  • out: 输出图片路径或文件夹;
  • mark: 水印文字内容;
  • opacity: 透明度(0-1);
  • angle: 旋转角度;
  • space: 水印间距;
  • size: 字体大小;

批量图片水印添加

代码语言:javascript
复制
import os
from watermarker.marker import add_mark

input_folder = "images"
output_folder = "watermarked_images"
watermark_text = "Nicholas与Pypi"

# 创建输出文件夹
os.makedirs(output_folder, exist_ok=True)

# 遍历文件夹中的所有文件
for filename in os.listdir(input_folder):
    if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
        # 构造完整的输出文件路径
        output_path = os.path.join(output_folder, filename)
        add_mark(file=os.path.join(input_folder, filename),
                 out=output_path,
                 mark=watermark_text,
                 opacity=0.3,
                 angle=30,
                 space=30,
                 size=50)

代码解释:

  • output_path = os.path.join(output_folder, filename):构造完整的输出文件路径,确保输出文件保存在 output_folder 中,并且文件名与输入文件相同。
  • add_mark(..., out=output_path, ...):将完整的输出文件路径传递给 add_mark 函数。

filestools库的水印功能不仅代码简洁,而且生成的水印效果专业,默认具有旋转和间隔排列的特性,能有效防止简单裁剪去除水印。

五、图形用户界面(GUI)水印工具

使用pythontkinter为水印工具开发图形界面,让非技术人员也能方便使用。

代码语言:javascript
复制
from PIL import Image, ImageDraw, ImageFont
import os
from watermarker.marker import add_mark
import tkinter as tk
from tkinter import filedialog, messagebox

class WatermarkApp:
    def __init__(self, root):
        self.root = root
        self.root.title("批量图片水印工具")
        
        # 输入文件夹
        tk.Label(root, text="图片文件夹:").grid(row=0, column=0, sticky="e")
        self.input_entry = tk.Entry(root, width=50)
        self.input_entry.grid(row=0, column=1)
        tk.Button(root, text="浏览", command=self.browse_input).grid(row=0, column=2)
        
        # 水印文字
        tk.Label(root, text="水印文字:").grid(row=1, column=0, sticky="e")
        self.watermark_entry = tk.Entry(root, width=50)
        self.watermark_entry.grid(row=1, column=1)
        
        # 输出文件夹
        tk.Label(root, text="输出文件夹:").grid(row=2, column=0, sticky="e")
        self.output_entry = tk.Entry(root, width=50)
        self.output_entry.grid(row=2, column=1)
        tk.Button(root, text="浏览", command=self.browse_output).grid(row=2, column=2)
        
        # 水印位置
        tk.Label(root, text="水印位置:").grid(row=3, column=0, sticky="e")
        self.position_var = tk.StringVar(value="bottom-right")
        positions = ["top-left", "top-right", "center", "bottom-left", "bottom-right"]
        for i, pos in enumerate(positions):
            tk.Radiobutton(root, text=pos, variable=self.position_var, value=pos).grid(row=3, column=1+i, sticky="w")
        
        # 透明度
        tk.Label(root, text="透明度(10-100):").grid(row=4, column=0, sticky="e")
        self.opacity_scale = tk.Scale(root, from_=10, to=100, orient=tk.HORIZONTAL)
        self.opacity_scale.set(50)
        self.opacity_scale.grid(row=4, column=1, columnspan=2, sticky="ew")
        
        # 执行按钮
        tk.Button(root, text="开始添加水印", command=self.process_images).grid(row=5, column=1)
        
    def browse_input(self):
        folder = filedialog.askdirectory()
        if folder:
            self.input_entry.delete(0, tk.END)
            self.input_entry.insert(0, folder)
    
    def browse_output(self):
        folder = filedialog.askdirectory()
        if folder:
            self.output_entry.delete(0, tk.END)
            self.output_entry.insert(0, folder)
    
    def process_images(self):
        input_folder = self.input_entry.get()
        output_folder = self.output_entry.get()
        watermark_text = self.watermark_entry.get()
        position = self.position_var.get()
        opacity = self.opacity_scale.get() / 100
        
        if not all([input_folder, output_folder, watermark_text]):
            messagebox.showerror("错误", "请填写所有必要字段!")
            return
        
        os.makedirs(output_folder, exist_ok=True)
        
        for filename in os.listdir(input_folder):
            if filename.lower().endswith(('.jpg', '.jpeg', '.png')):
                try:
                    image = Image.open(os.path.join(input_folder, filename)).convert('RGBA')
                    watermark = Image.new('RGBA', image.size, (0, 0, 0, 0))
                    draw = ImageDraw.Draw(watermark)
                    
                    # 计算字体大小
                    font_size = int(min(image.size) * 0.05)
                    font = ImageFont.truetype("simhei.ttf", font_size)
                    
                    # 计算水印位置
                    bbox = draw.textbbox((0, 0), watermark_text, font=font)
                    text_width = bbox[2] - bbox[0]
                    text_height = bbox[3] - bbox[1]
                    x, y = self.calculate_position(image.size, (text_width, text_height), position)
                    
                    # 绘制水印
                    draw.text((x, y), watermark_text, font=font, fill=(0, 255, 0, int(255 * opacity)))
                    
                    # 合并保存
                    combined = Image.alpha_composite(image, watermark)
                    combined.convert('RGB').save(os.path.join(output_folder, filename))
                    
                except Exception as e:
                    print(f"处理 {filename} 时出错: {e}")
        
        messagebox.showinfo("完成", "水印添加完成!")
    
    def calculate_position(self, base_size, text_size, position):
        if position == "top-left":
            return (20, 20)
        elif position == "top-right":
            return (base_size[0] - text_size[0] - 20, 20)
        elif position == "center":
            return ((base_size[0] - text_size[0]) // 2, (base_size[1] - text_size[1]) // 2)
        elif position == "bottom-left":
            return (20, base_size[1] - text_size[1] - 20)
        else:  # bottom-right
            return (base_size[0] - text_size[0] - 20, base_size[1] - text_size[1] - 20)

“无他,惟手熟尔”!有需要的用起来。

如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nicholas与Pypi 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、安装库:
  • 二、单张图片添加水印
    • 方法一:直接在原图上绘制文本水印
    • 方法二:使用透明图层添加水印
  • 三、批量图片添加水印
    • 批量处理实现
    • 功能说明:
  • 四、使用filestools库
    • 单张图片水印添加
    • 批量图片水印添加
    • 代码解释:
  • 五、图形用户界面(GUI)水印工具
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档