当前位置: 代码网 > it编程>前端脚本>Python > Python Pillow库批量为图片添加文字水印或图片水印

Python Pillow库批量为图片添加文字水印或图片水印

2026年08月28日 Python 我要评论
场景引入公司有 5000 张产品图片需要加上公司 logo 水印,或 2000 张员工工牌照片需要加盖"仅限内部使用"的文字水印。用 photoshop 一张一张处理,一个人都要干

场景引入

公司有 5000 张产品图片需要加上公司 logo 水印,或 2000 张员工工牌照片需要加盖"仅限内部使用"的文字水印。用 photoshop 一张一张处理,一个人都要干半天。

本节教你用 python 的 pillow 库,批量为图片添加文字水印或图片水印,每秒处理几十张。

技术原理

使用 pillow(pil fork)库操作图片:

水印类型实现方式
文字水印imagedraw.text()
图片水印(logo)image.paste()image.alpha_composite()
半透明水印创建透明图层 + image.blend()
倾斜水印image.rotate()

原图 → 创建透明图层 → 绘制水印 → 叠加到原图 → 保存

环境准备

pip install pillow

完整代码

from pil import image, imagedraw, imagefont, imageenhance
import os
from pathlib import path

# ==================== 方案 1:文字水印 ====================
def add_text_watermark(input_image, output_image, text="内部资料",
                       position="center", font_size=40, color=(255, 255, 255, 128),
                       angle=0):
    """
    为图片添加文字水印

    参数:
        input_image: 输入图片路径
        output_image: 输出图片路径
        text: 水印文字
        position: 位置 'center'/'bottom-right'/'bottom-left'/'top-right'/'top-left'
        font_size: 字体大小
        color: 字体颜色 (r, g, b, a)
        angle: 旋转角度(0=水平,-30=左倾斜)
    """
    # 打开图片
    img = image.open(input_image).convert('rgba')

    # 创建透明图层
    txt_layer = image.new('rgba', img.size, (255, 255, 255, 0))
    draw = imagedraw.draw(txt_layer)

    # 获取字体
    try:
        font = imagefont.truetype("c:/windows/fonts/msyh.ttc", font_size)  # 微软雅黑
    except:
        font = imagefont.load_default()

    # 计算文字大小和位置
    bbox = draw.textbbox((0, 0), text, font=font)
    text_width = bbox[2] - bbox[0]
    text_height = bbox[3] - bbox[1]

    img_width, img_height = img.size

    positions = {
        'center': ((img_width - text_width) // 2, (img_height - text_height) // 2),
        'bottom-right': (img_width - text_width - 20, img_height - text_height - 20),
        'bottom-left': (20, img_height - text_height - 20),
        'top-right': (img_width - text_width - 20, 20),
        'top-left': (20, 20),
    }

    x, y = positions.get(position, positions['center'])

    # 如果需要旋转
    if angle != 0:
        # 创建更大的图层以容纳旋转后的文字
        big_layer = image.new('rgba', (img_width * 2, img_height * 2), (255, 255, 255, 0))
        big_draw = imagedraw.draw(big_layer)
        big_draw.text((img_width // 2, img_height // 2), text, font=font, fill=color)
        big_layer = big_layer.rotate(angle, expand=0)
        txt_layer = big_layer.crop((img_width // 2, img_height // 2,
                                     img_width // 2 + img_width,
                                     img_height // 2 + img_height))
    else:
        draw.text((x, y), text, font=font, fill=color)

    # 叠加
    result = image.alpha_composite(img, txt_layer)

    # 保存(转回 rgb 以便保存为 jpeg)
    result = result.convert('rgb')
    result.save(output_image, quality=95)
    print(f"文字水印: {os.path.basename(input_image)}")


# ==================== 方案 2:图片水印(logo) ====================
def add_image_watermark(input_image, output_image, logo_path,
                       position="bottom-right", opacity=0.5, scale=0.15):
    """
    为图片添加 logo 水印

    参数:
        input_image: 输入图片
        output_image: 输出图片
        logo_path: logo 图片路径(建议 png 透明背景)
        position: 位置
        opacity: 透明度(0-1,1=完全不透明)
        scale: logo 相对原图大小的比例(0.15=15%)
    """
    img = image.open(input_image).convert('rgba')

    # 打开 logo
    logo = image.open(logo_path).convert('rgba')

    # 缩放 logo
    new_logo_size = (int(img.width * scale), int(img.height * scale * logo.height / logo.width))
    logo = logo.resize(new_logo_size, image.lanczos)

    # 设置 logo 透明度
    if opacity < 1:
        # 调整 alpha 通道
        r, g, b, a = logo.split()
        a = a.point(lambda x: int(x * opacity))
        logo = image.merge('rgba', (r, g, b, a))

    # 计算位置
    positions = {
        'center': ((img.width - logo.width) // 2, (img.height - logo.height) // 2),
        'bottom-right': (img.width - logo.width - 20, img.height - logo.height - 20),
        'bottom-left': (20, img.height - logo.height - 20),
        'top-right': (img.width - logo.width - 20, 20),
        'top-left': (20, 20),
    }

    x, y = positions.get(position, positions['bottom-right'])

    # 创建透明图层并粘贴 logo
    watermark_layer = image.new('rgba', img.size, (0, 0, 0, 0))
    watermark_layer.paste(logo, (x, y))

    # 叠加
    result = image.alpha_composite(img, watermark_layer)
    result = result.convert('rgb')
    result.save(output_image, quality=95)
    print(f"logo水印: {os.path.basename(input_image)}")


# ==================== 方案 3:平铺水印(全屏重复) ====================
def add_tiled_watermark(input_image, output_image, text="内部资料",
                        font_size=30, color=(255, 255, 255, 50), angle=-30, spacing=150):
    """
    添加平铺水印(全屏重复文字)
    """
    img = image.open(input_image).convert('rgba')
    txt_layer = image.new('rgba', img.size, (255, 255, 255, 0))
    draw = imagedraw.draw(txt_layer)

    try:
        font = imagefont.truetype("c:/windows/fonts/msyh.ttc", font_size)
    except:
        font = imagefont.load_default()

    # 计算文字大小
    bbox = draw.textbbox((0, 0), text, font=font)
    text_width = bbox[2] - bbox[0]
    text_height = bbox[3] - bbox[1]

    # 平铺
    y = 0
    while y < img.height:
        x = 0
        row_offset = (y // spacing) % 2 * (spacing // 2)  # 错行排列
        while x < img.width:
            draw.text((x + row_offset, y), text, font=font, fill=color)
            x += text_width + spacing
        y += text_height + spacing

    result = image.alpha_composite(img, txt_layer)
    result = result.convert('rgb')
    result.save(output_image, quality=95)
    print(f"平铺水印: {os.path.basename(input_image)}")


# ==================== 批量处理 ====================
def batch_add_watermark(input_dir, output_dir, watermark_func, **kwargs):
    """
    批量为文件夹中的所有图片添加水印
    """
    input_path = path(input_dir)
    output_path = path(output_dir)
    output_path.mkdir(parents=true, exist_ok=true)

    image_extensions = {'.jpg', '.jpeg', '.png', '.bmp', '.webp', '.tiff'}
    count = 0

    for file_path in input_path.iterdir():
        if file_path.is_file() and file_path.suffix.lower() in image_extensions:
            output_file = output_path / file_path.name
            watermark_func(str(file_path), str(output_file), **kwargs)
            count += 1

    print(f"\n批量水印完成: {count} 张图片")


# ==================== 使用示例 ====================
if __name__ == "__main__":
    # 单个文件
    # add_text_watermark("工牌照片.jpg", "工牌_水印.jpg", text="内部资料", position="center", font_size=50)

    # 批量文字水印
    batch_add_watermark(
        input_dir="原始工牌照片",
        output_dir="已加水印",
        watermark_func=add_text_watermark,
        text="仅限内部使用",
        position="center",
        font_size=40,
    )

    # 批量 logo 水印
    # batch_add_watermark(
    #     input_dir="产品图片",
    #     output_dir="已加logo",
    #     watermark_func=add_image_watermark,
    #     logo_path="company_logo.png",
    #     position="bottom-right",
    #     opacity=0.7,
    #     scale=0.1
    # )

    # 平铺水印(防截图)
    # batch_add_watermark(
    #     input_dir="机密文档截图",
    #     output_dir="平铺水印",
    #     watermark_func=add_tiled_watermark,
    #     text="机密文件",
    #     font_size=25,
    #     angle=-30,
    # )

常见问题

q1:中文水印显示为方框?

需要指定中文字体路径:

font = imagefont.truetype("c:/windows/fonts/msyh.ttc", font_size)  # 微软雅黑
# 或
font = imagefont.truetype("c:/windows/fonts/simsun.ttc", font_size)  # 宋体

q2:水印太显眼覆盖了图片内容?

调整 color 的 alpha 值(第四个参数):

color=(255, 255, 255, 50)  # alpha=50,更透明

q3:保存 png 后水印不见了?

确保保存时使用 rgba 模式并指定 png 格式:

result.save(output_image, 'png')

总结

水印类型函数适用场景
文字水印add_text_watermark()版权声明
logo 水印add_image_watermark()品牌标识
平铺水印add_tiled_watermark()防泄漏标记

本节掌握了为图片批量添加水印的能力。

到此这篇关于python pillow库批量为图片添加文字水印或图片水印的文章就介绍到这了,更多相关python图片添加水印内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com