【Python】PIL给图片添加水印源码解释

查看 44|回复 0
作者:moduwusuowei   
给图片添加水印
以下是一个添加水印的方法,你可以将其放在一个单独的 Python 文件中,然后在需要添加水印的地方调用该方法即可:
from PIL import Image, ImageDraw, ImageFont
def add_watermark(image_path, tehttps://img-blog.csdnimg.cn/09d97f5f1220486cad25f998bbc49092.pngxt, font_path, font_size=40, fill=(255, 255, 255, 128)):
    """
    在图片上添加水印
    :param image_path: 图片路径
    :param text: 水印文本
    :param font_path: 字体文件路径
    :param font_size: 字体大小,默认为 40
    :param fill: 水印颜色,默认为白色半透明
    :return: None
    """
    with Image.open(image_path) as image:
        draw = ImageDraw.Draw(image)
        width, height = image.size
        font = ImageFont.truetype(font_path, font_size)
        text_width, text_height = draw.textsize(text, font=font)
        x = int((width - text_width) / 2)
        y = int((height - text_height) / 2)
        draw.text((x, y), text, font=font, fill=fill)
        image.save(image_path)
该方法接受五个参数:
  • image_path:需要添加水印的图片路径;
  • text:水印文本;
  • font_path:字体文件路径;
  • font_size:字体大小,默认为 40;
  • fill:水印颜色,默认为白色半透明。

    你可以根据需要修改这些参数。
    使用该方法的示例代码如下:
    add_watermark('image.jpg', 'Hello, world!', 'simsun.ttc', font_size=50)
    该代码会在 image.jpg 图片中添加一个水印,水印文本为 Hello, world!,字体为 simsun.ttc,字体大小为 50。
    fill参数解释:
    fill 参数指定了水印的颜色。在 PIL 库中,颜色是以一个四元组来表示的,四元组中的四个值分别代表红、绿、蓝和透明度,取值范围为 0 到 255。例如,(255, 0, 0, 128) 表示红色半透明。
    在 add_watermark() 方法中,我们将默认的 fill 参数设置为 (255, 255, 255, 128),即白色半透明,这样可以让水印不会完全遮挡住原图。你可以根据需要修改该参数,例如将水印颜色修改为红色,可以将 fill 参数修改为 (255, 0, 0, 128)。
    textbbox参数解释
    textbbox() 方法是 Pillow 库中 ImageDraw 模块提供的一个函数,用于计算绘制文本所需的矩形框的大小。该方法的语法如下:
    ImageDraw.Draw.textbbox(xy, text, font=None, spacing=0, align='left')
    其中,各参数的含义如下:
  • xy:一个二元组 (x, y),表示文本的起始位置,即文本框的左上角坐标。
  • text:表示要绘制的文本内容。
  • font:表示字体对象,可以使用 ImageFont.truetype() 方法创建。
  • spacing:表示行与行之间的间距,默认为 0。
  • align:表示文本的水平对齐方式,可以是 'left'、'center' 或 'right'。

    textbbox() 方法会根据文本内容、字体和起始位置等信息计算出文本框的大小,返回一个四元组 (x0, y0, x1, y1),表示文本框的左上角和右下角坐标。其中,(x0, y0) 表示文本框的左上角坐标,(x1, y1) 表示文本框的右下角坐标。
    在绘制文本时,我们可以使用 textbbox() 方法先计算出文本框的大小,然后根据文本框的大小来计算文本的位置,从而确保文本在图片中居中或居左等对齐方式。
    异常处理
    warning提示:

    DeprecationWarning: textsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use textbbox or textlength instead.  text_width, text_height = draw.textsize(text, font=font)

    解决方法:
    这个警告是因为在 Pillow 库的未来版本中,textsize() 方法将被弃用,建议使用 textbbox() 或 textlength() 方法代替。因此,在编写代码时,我们应该尽可能避免使用 textsize() 方法。
    根据警告信息,你可以将代码中的 textsize() 方法替换为 textbbox() 或 textlength() 方法。例如,将上面的代码修改为:
    width, height = image.size
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype(font_path, font_size)
    text_width, text_height = draw.textbbox((0, 0), text, font=font)
    x = int((width - text_width) / 2)
    y = int((height - text_height) / 2)
    draw.text((x, y), text, font=font, fill=fill)
    在上面的代码中,我们使用 textbbox() 方法来计算文本的宽度和高度,然后根据图片大小和文本大小来计算出文本在图片中的位置,最后将文本绘制到图片上。这样可以避免使用 textsize() 方法时出现的警告。
    异常draw.textbbox
    text_width, text_height = draw.textbbox((10, 10), text, font=font)代码这个地方抛出异常Error: too many values to unpack (expected 2)
    这个错误通常是由于 textbbox() 方法返回的四元组 (x0, y0, x1, y1) 与期望的二元组 (text_width, text_height) 不匹配引起的。
    要解决这个问题,您可以使用四元组中的左上角坐标 (x0, y0) 和右下角坐标 (x1, y1) 计算文本的宽度和高度,例如:
    # 计算文本框大小
    bbox = draw.textbbox((10, 10), text, font=font)
    # 计算文本宽度和高度
    text_width = bbox[2] - bbox[0]
    text_height = bbox[3] - bbox[1]
    这里,我们使用 bbox[2] - bbox[0] 计算文本的宽度,使用 bbox[3] - bbox[1] 计算文本的高度。这样,就可以将计算出的宽度和高度存储在 text_width 和 text_height 变量中,以供后续使用。
    请注意,在使用 textbbox() 方法时,返回的四元组中的值的顺序是 (x0, y0, x1, y1),因此,您需要根据需要来提取相应的值。
    from PIL import Image, ImageDraw, ImageFont
    def add_watermark(image_path, text, font_path, font_size=40, opacity=0.5, fill=(255, 102, 0, 128)):
        """
        在图片上添加水印
        :param image_path: 图片路径
        :param text: 水印文本
        :param font_path: 字体文件路径
        :param font_size: 字体大小,默认为 40
        :param opacity: 水印透明度,默认为 0.5
        :param fill: 水印颜色,默认为白色半透明
        :return: None
        """
        with Image.open(file_path) as image:
            draw = ImageDraw.Draw(image)
            width, height = image.size
            font = ImageFont.truetype(font_path, font_size)
            print(333)
            # text_width, text_height = draw.textbbox((10, 10), text, font=font)
            # 计算文本框大小
            bbox = draw.textbbox((10, 10), text, font=font)
            # 计算文本宽度和高度
            text_width = bbox[2] - bbox[0]
            text_height = bbox[3] - bbox[1]
            print(f"=== text_width, text_height  {text_width, text_height }")
            x = int((width - text_width) / 2)
            y = int((height - text_height) / 2)
            draw.text((x, y), text, font=font, fill=FILL)
            image.save(file_path)
    中文显示异常
    原始图片

    调用方式:
    if __name__ == '__main__':
        add_watermark('test.png', '测试!', 'simsunb.ttf', font_size=50)

    我们期待图片中间有:测试!,水印显示在图片上,实际结果我们已经看到,看来还是哪里有问题;
    修改中文字体库引用就可以了
    if __name__ == '__main__':
        # add_watermark('test.png', '测试!', 'simsunb.ttf', font_size=50)
        add_watermark('test.png', '测试!', r'C:\Windows\Fonts\微软雅黑\msyh.ttc', font_size=50)

    刚才我用了:C:\Windows\Fonts\微软雅黑\msyh.ttc这个路径,跟大家提一下这是Windows系统字体默认的存储位置;
    到这里就实现给图片添加水印的基本操作了,赶紧动手试试吧;
    这个图片实在是不知道怎么上传了,也可以访问:https://blog.csdn.net/qq_41604569/article/details/130720303

    水印, 文本

  • 您需要登录后才可以回帖 登录 | 立即注册

    返回顶部