Python 批量加水印

看看效果图:在这里插入图片描述

import os
import math
from PIL import Image, ImageDraw, ImageFont


def add_watermark(image_path, output_path, watermark_text, opacity=50):
    """
    给图片添加重复文字水印

    参数:
    image_path -- 输入图片路径
    output_path -- 输出图片路径
    watermark_text -- 水印文字
    opacity -- 水印透明度 (0-255)
    """
    try:
        # 打开原始图片
        with Image.open(image_path) as img:
            # 创建一个与原图同样大小的透明图层用于绘制水印
            watermark = Image.new('RGBA', img.size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(watermark)

            # 尝试加载字体,如果失败使用默认字体
            try:
                # 加载字体,根据需要更改字体大小
                font_size = min(img.width, img.height) // 20  # 动态调整字体大小
                font = ImageFont.truetype("arial.ttf", font_size)
            except IOError:
                # 如果无法加载指定字体,使用默认字体
                font = ImageFont.load_default()

            # 计算水印文字的大小 - 修复textsize问题
            # 在新版本PIL中,textsize已被替换为textbbox或textlength
            if hasattr(draw, "textlength"):
                text_width = draw.textlength(watermark_text, font=font)
                # 估算高度
                text_height = font_size
            elif hasattr(draw, "textbbox"):
                bbox = draw.textbbox((0, 0), watermark_text, font=font)
                text_width = bbox[2] - bbox[0]
                text_height = bbox[3] - bbox[1]
            else:
                # 如果都不支持,给予估计值
                text_width = font_size * len(watermark_text) * 0.6
                text_height = font_size

            # 根据图片大小,计算水印排列的行列数
            spacing = min(img.width, img.height) // 5  # 水印之间的间距

            # 确定水印的行列数
            rows = int(img.height / spacing) + 2
            cols = int(img.width / spacing) + 2

            # 添加偏移量使水印交错排列
            offset_x = spacing // 3
            offset_y = spacing // 3

            # 绘制重复的水印
            for row in range(rows):
                for col in range(cols):
                    # 计算每个水印的位置,使其交错分布
                    pos_x = col * spacing
                    # 偶数行偏移
                    if row % 2 == 0:
                        pos_x += offset_x

                    pos_y = row * spacing
                    # 偶数列偏移
                    if col % 2 == 0:
                        pos_y += offset_y

                    # 在不同位置绘制透明水印
                    draw.text((pos_x, pos_y), watermark_text,
                              fill=(0, 0, 0, opacity), font=font)

            # 如果原图是RGBA模式,直接使用,否则转换为RGBA
            if img.mode != 'RGBA':
                img = img.convert('RGBA')

            # 将水印图层合并到原图
            result = Image.alpha_composite(img, watermark)

            # 保存结果
            if output_path.lower().endswith('.jpg') or output_path.lower().endswith('.jpeg'):
                # JPEG不支持透明度,将其转换为RGB并保存
                result = result.convert('RGB')

            result.save(output_path)
            print(f"已添加水印: {os.path.basename(image_path)} -> {os.path.basename(output_path)}")
            return True
    except Exception as e:
        print(f"处理图片 {image_path} 时出错: {e}")
        return False


def batch_add_watermark(input_folder, output_folder, watermark_text):
    """
    批量给文件夹内的图片添加水印

    参数:
    input_folder -- 输入图片文件夹
    output_folder -- 输出图片文件夹
    watermark_text -- 水印文字
    """
    # 确保输出文件夹存在
    os.makedirs(output_folder, exist_ok=True)

    # 支持的图片扩展名
    supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff']

    # 成功和失败计数
    success_count = 0
    fail_count = 0

    # 检查输入文件夹是否存在
    if not os.path.exists(input_folder):
        print(f"错误: 输入文件夹 '{input_folder}' 不存在!")
        return

    # 打印当前工作目录和寻找的文件夹
    print(f"当前工作目录: {os.getcwd()}")
    print(f"查找图片的文件夹: {input_folder}")

    # 获取文件夹中的所有文件
    files = []
    try:
        files = os.listdir(input_folder)
        print(f"在文件夹中找到 {len(files)} 个文件")
    except Exception as e:
        print(f"列出文件夹内容时出错: {e}")
        return

    # 遍历输入文件夹中的所有文件
    for filename in files:
        # 获取文件完整路径
        input_path = os.path.join(input_folder, filename)

        # 忽略子目录
        if os.path.isdir(input_path):
            print(f"跳过子目录: {filename}")
            continue

        # 获取文件扩展名
        file_ext = os.path.splitext(filename)[1].lower()

        # 检查是否为支持的图片格式
        if file_ext in supported_formats:
            output_path = os.path.join(output_folder, filename)

            # 如果是JPEG格式,确保正确处理
            if file_ext in ['.jpg', '.jpeg']:
                # JPEG保存为JPG格式
                output_path = os.path.splitext(output_path)[0] + '.jpg'

            print(f"处理图片: {input_path}")
            # 添加水印
            if add_watermark(input_path, output_path, watermark_text):
                success_count += 1
            else:
                fail_count += 1
        else:
            print(f"跳过不支持的文件格式: {filename}")

    print(f"\n处理完成! 成功: {success_count}, 失败: {fail_count}")


if __name__ == "__main__":
    # 可自定义的水印文本
    watermark_text = "TEST "  # 在这里修改水印文字

    # 指定输入和输出文件夹
    input_folder = "img"  # 输入图片文件夹
    output_folder = "result"  # 输出图片文件夹

    print("=== 图片批量水印添加工具 ===")
    print(f"水印文字: '{watermark_text}'")
    print(f"输入文件夹: '{input_folder}'")
    print(f"输出文件夹: '{output_folder}'")

    # 开始批量添加水印
    batch_add_watermark(input_folder, output_folder, watermark_text)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AIOT魔法师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值