[Python] PIL adds watermark to pictures with the most complete code explanation

Add watermark to pictures

The following is a method to add watermark, you can put it in a separate Python file, and then call this method where you need to add watermark:

from PIL import Image, ImageDraw, ImageFont


def add_watermark(image_path, text, 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)

The method accepts five parameters:

  • image_path: the path of the image that needs to be watermarked;
  • text: watermark text;
  • font_path: font file path;
  • font_size: font size, the default is 40;
  • fill: Watermark color, the default is white and translucent.

You can modify these parameters as needed.

The sample code using this method is as follows:

add_watermark('image.jpg', 'Hello, world!', 'simsun.ttc', font_size=50)

This code will add a watermark to image.jpgthe image with text of Hello, world!, font of simsun.ttc, and font size of 50.

fill parameter explanation:

fillThe parameter specifies the color of the watermark. In the PIL library, a color is represented by a quadruple. The four values ​​in the quadruple represent red, green, blue and transparency respectively, and the value range is from 0 to 255. For example, (255, 0, 0, 128)to represent red translucency.

In add_watermark()the method , we fillset the default parameter to (255, 255, 255, 128)be white and translucent, so that the watermark will not completely cover the original image. You can modify this parameter as needed, for example, to change the watermark color to red, you can modify fillthe parameter to (255, 0, 0, 128).

textbbox parameter explanation

textbbox()The method is a function provided by ImageDrawthe module , which is used to calculate the size of the rectangle needed to draw the text. The syntax of the method is as follows:

ImageDraw.Draw.textbbox(xy, text, font=None, spacing=0, align='left')

Among them, the meaning of each parameter is as follows:

  • xy: A two-tuple (x, y)indicating the starting position of the text, that is, the coordinates of the upper left corner of the text box.
  • text: Indicates the text content to be drawn.
  • font: Represents a font object, which can be created using ImageFont.truetype()the method .
  • spacing: Indicates the spacing between lines, the default is 0.
  • align: Indicates the horizontal alignment of the text, which can be 'left', 'center'or 'right'.

textbbox()The method calculates the size of the text box based on information such as text content, font, and starting position, and returns a 4-tuple (x0, y0, x1, y1)indicating the coordinates of the upper-left corner and lower-right corner of the text box. Among them, (x0, y0)represents the coordinates of the upper left corner of the text box, and (x1, y1)represents the coordinates of the lower right corner of the text box.

When drawing text, we can use textbbox()the method to first calculate the size of the text box, and then calculate the position of the text according to the size of the text box, so as to ensure that the text is centered or left aligned in the picture.

exception handling

warning prompt:

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)

Solution:

This warning is because in a future version of the Pillow library, textsize()the method will be deprecated and it is recommended to use textbbox()the or textlength()method instead. Therefore, when writing code, we should avoid using textsize()the method .

According to the warning message, you can replace textsize()the method with textbbox()the or textlength()method . For example, modify the code above to:

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)

In the above code, we use textbbox()the method to calculate the width and height of the text, then calculate the position of the text in the image according to the size of the image and the size of the text, and finally draw the text on the image. This avoids warnings when using textsize()the method .

exception draw.textbbox

text_width, text_height = draw.textbbox((10, 10), text, font=font) This part of the code throws an exception Error: too many values ​​to unpack (expected 2)

This error is usually caused by a mismatch between the 4-tuple returned by textbbox()the method and(x0, y0, x1, y1) the expected 2-tuple .(text_width, text_height)

To fix this, you can calculate the width and height of the text using the top-left (x0, y0)and , for example:(x1, y1)

# 计算文本框大小
bbox = draw.textbbox((10, 10), text, font=font)

# 计算文本宽度和高度
text_width = bbox[2] - bbox[0]
text_height = bbox[3] - bbox[1]

Here, we use to bbox[2] - bbox[0]calculate the width of the text and to bbox[3] - bbox[1]calculate the height of the text. This way, the calculated width and height can be stored in the text_widthand text_heightvariables for later use.

Note that when using textbbox()the method , the values ​​in the returned 4-tuple are in order (x0, y0, x1, y1), so you need to extract the corresponding values ​​as needed.

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)
Chinese display exception

Original Image
insert image description here

Call method:

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

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-jYNI8pkj-1684290601180) (Excel and PIL.assets/image-20230517102532955.png)]

We expect that there is: test! in the middle of the picture, and the watermark is displayed on the picture. We have seen the actual result, and it seems that there is still something wrong;

Just modify the Chinese font library reference

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)

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-HzCecq1L-1684290601181) (Excel and PIL.assets/image-20230517102808833.png)]

Just now I used: C:\Windows\Fonts\Microsoft Yahei\msyh.ttc this path, I would like to mention to you that this is the default storage location of Windows system fonts;

At this point, the basic operation of adding watermark to the picture has been realized, so let's try it out quickly;

Guess you like

Origin blog.csdn.net/qq_41604569/article/details/130720303