Archive:

图像添加水印代码


1、自动文字生成版

# add_watermark.py

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


class WaterMark():
    def __init__(self, 
                 font_folder="", 
                 font_size=20,
                 ):
                 
        super().__init__()
        
        # 创建字体对象
        self.font_dict = {}
        self.font_path_dict = {}
        for root, dirs, files in os.walk(font_folder):
            for file in files:
                if file.lower().endswith(('ttf', '.ttc')):
                    file_path = os.path.join(root, file)
                    file_name = os.path.splitext(os.path.basename(file_path))[0]
                    self.font_dict[file_name] = ImageFont.truetype(file_path, font_size)
                    self.font_path_dict[file_name] = file_path
        # print(self.font_dict)
        # print(self.font_path_dict)
        self.font_size = font_size
        

    def add(self, 
            # image_path, 
            image,
            watermark_text="None Text!", 
            watermark_mode='1',
            watermark_height=None,
            position_x=0, 
            position_y=0, 
            font_name='arial', 
            font_size=20,
            # font_color="black", 
            ):  
     
        # 打开原始图片
        # image = Image.open(image_path)  
            
        # 计算文字尺寸
        dummy_image = Image.new('RGB', (1, 1))
        dummy_draw = ImageDraw.Draw(dummy_image)
        
        font = self.font_dict[font_name] if font_size == self.font_size else ImageFont.truetype(self.font_path_dict[font_name], font_size)
        self.text_bbox = dummy_draw.textbbox((0, 0), watermark_text, font=font)
        # print(text_bbox)
        self.text_width = self.text_bbox[2] - self.text_bbox[0]
        self.text_height = self.text_bbox[3] - self.text_bbox[1]
        # text_width, text_height = dummy_draw.textsize(watermark_text, font=font)
        # print("text_bbox:", self.text_bbox, "text_width:", self.text_width, "text_height:", self.text_height)
        
        
        if watermark_mode == '2':   # 'overlay'
            result = self.overlay(
                        image=image, 
                        watermark_text=watermark_text, 
                        position_x=position_x, 
                        position_y=position_y, 
                        font=font, 
                        font_color="white", 
                        )
        elif watermark_mode == '1':   # 'concatenate'
            result = self.concatenate(
                            image=image, 
                            watermark_text=watermark_text, 
                            watermark_height=watermark_height,
                            position_x=position_x, 
                            position_y=position_y, 
                            font=font, 
                            font_color="black", 
                            )
        else:

            # 随机选择并调用一个函数
            chosen_mode = random.choice(['1', '2'])
            # print("chosen_mode:", chosen_mode)
            if chosen_mode == '2':
                position_x = 20
                position_y = -10
            elif chosen_mode == '1':
                position_x = 20
                position_y = watermark_height//2 - self.text_height//2 if watermark_height else self.text_height
                # print(watermark_height, position_y)
                
            result = self.add(
                         # image_path=image_path, 
                         image=image,
                         watermark_text=watermark_text, 
                         watermark_mode=chosen_mode,
                         watermark_height=watermark_height,
                         position_x=position_x, 
                         position_y=position_y, 
                         font_name=font_name, 
                         font_size=font_size,
                         )
        return result
        
        
    def overlay(self, 
                image, 
                watermark_text="None Text!", 
                position_x=0, 
                position_y=0, 
                font=None, 
                font_color="white", 
                ): 

        # 叠加模式
        if position_y >= image.height - self.text_height:
            position_y = image.height - self.text_height
        elif self.text_height - image.height <= position_y <= 0:
            position_y = image.height - self.text_height + position_y
        elif position_y <= self.text_height - image.height:
            position_y = 0 
            
        # print("position_x:", position_x, "position_y:", position_y)   
        
        logo_image = Image.open('./watermarks/AIGClogo.png').convert("RGBA")
        new_text_height = int(self.text_height * 1.1)
        new_width = int(logo_image.width * new_text_height / logo_image.height)
        logo_image_resized = logo_image.resize((new_width, new_text_height), )
        # logo_image_resized = logo_image.resize((new_width, new_text_height), Image.NEAREST)
        
        # 创建一个新的透明图层,尺寸与原始图像相同
        watermark_background = Image.new('RGBA', image.size, (0, 0, 0, 0))
        # 在背景上绘制文本
        draw = ImageDraw.Draw(watermark_background)
        watermark_background.paste(image, (0, 0))
        draw.text((position_x, position_y-self.text_bbox[1]), watermark_text, font=font, fill=font_color)
    
        # 将 "AIGC" 图像粘贴到文字水印图层上
        AIGC_position = (position_x + self.text_width + 5, position_y - int(self.text_height * 0.05)) 
        watermark_background.paste(logo_image_resized, AIGC_position, logo_image_resized)
        
        # 将文字图层叠加到原图上
        # watermarked = Image.alpha_composite(image.convert('RGBA'), watermark_background)   # 白色文字线条会变淡变细。
        
        return watermark_background.convert('RGB')                
        
        
    def concatenate(self, 
                    image, 
                    watermark_text="None Text!", 
                    watermark_height=None,
                    position_x=0, 
                    position_y=0, 
                    font=None,
                    font_color="black", 
                    ):           

        # 拼接模式
        if watermark_height is None:
            watermark_height = self.text_height * 3
        greybg_image = Image.open('./watermarks/greybg.png').convert("RGBA")
        # watermark_height = min(watermark_height, greybg_image.height)
        # print("watermark_height:", watermark_height)
            
        if position_y >= watermark_height - self.text_height:
            position_y = watermark_height - self.text_height
        elif self.text_height - watermark_height <= position_y <= 0:
            position_y = watermark_height - self.text_height + position_y
        elif position_y <= self.text_height - watermark_height:
            position_y = 0 
            
        # print("position_x:", position_x, "position_y:", position_y)   
           
        # greybg_new_width = int(greybg_image.width * watermark_height / greybg_image.height)
        # greybg_image_resized = greybg_image.resize((greybg_new_width, watermark_height), )
        greybg_image_resized = greybg_image.resize((image.width//2, watermark_height), )    
        logo_image = Image.open('./watermarks/reddot.png').convert("RGBA")
        logo_new_width = int(logo_image.width * self.text_height / logo_image.height)
        logo_image_resized = logo_image.resize((logo_new_width//2, self.text_height//2))
     
        # 创建文字背景图层
        watermark_background = Image.new('RGB',  (image.width, watermark_height), "white")
        watermark_background.paste(greybg_image_resized, (watermark_background.width - greybg_image_resized.width, watermark_background.height - greybg_image_resized.height), greybg_image_resized)
        # 在背景上绘制文本
        draw = ImageDraw.Draw(watermark_background)
        draw.text((position_x, position_y-self.text_bbox[1]), watermark_text, font=font, fill=font_color)
        ## 计算文字尺寸
        dummy_image = Image.new('RGB', (1, 1))
        dummy_draw = ImageDraw.Draw(dummy_image)
        tmp_text_bbox = dummy_draw.textbbox((0, 0), "AIGC Portrait", font=font)
        tmp_text_width = tmp_text_bbox[2] - tmp_text_bbox[0]
        tmp_text_height = tmp_text_bbox[3] - tmp_text_bbox[1]
        draw.text((image.width - tmp_text_width -30, position_y-self.text_bbox[1]), "AIGC Portrait", font=font, fill="black")
        
        AIGC_position = (position_x + self.text_width + 5, position_y + self.text_height//4) 
        watermark_background.paste(logo_image_resized, AIGC_position, logo_image_resized)
        
        # 将文字图层拼接到原图下方
        watermarked = Image.new('RGB', (image.width, image.height + watermark_height))
        watermarked.paste(image, (0, 0))
        watermarked.paste(watermark_background, (0, image.height))
        return watermarked.convert('RGB')
        
      
# 使用示例  
if __name__ == "__main__":
    wm = WaterMark(font_folder="./fonts", font_size=20,)
    watermarked_image = wm.add(image_path="20240613-112009.jpg", 
                               watermark_text="AI_CV算法组测试", 
                               watermark_mode='2',
                               watermark_height=None,
                               position_x=20, 
                               position_y=-10, 
                               font_name='STZHONGS', 
                               font_size=25,)
    # 保存结果
    watermarked_image.save("watermarked_image112.jpg")    
     

1、水印贴图版

# add_watermark.py

from PIL import Image
import os
import random


class WaterMark():
    def __init__(self, 
                 watermark_folder="", 
                 ):
                 
        super().__init__()

        self.watermark_1 = {}
        self.watermark_2 = {}
        if watermark_folder:
            for root, dirs, files in os.walk(watermark_folder):
                image_list = []
                for file in files:
                    if file.lower().endswith(('.jpg', )):
                        file_path = os.path.join(root, file)
                        file_name = os.path.splitext(os.path.basename(file_path))[0]
                        self.watermark_1[file_name] = Image.open(file_path)                      
                    if file.lower().endswith(('.png', )):
                        file_path = os.path.join(root, file)
                        file_name = os.path.splitext(os.path.basename(file_path))[0]
                        self.watermark_2[file_name] = Image.open(file_path)   
            # print(self.watermark_1) 
            # print(self.watermark_2) 
        

    def add(self, 
            image,
            watermark_name="aaa_30_bb_5g", 
            watermark_mode='1',
            position_x=None, 
            position_y=None, 
            ):  
        # print(image, watermark_name, watermark_mode, position_x, position_y)
        
        
        if watermark_mode == '2':   # 'overlay'
            result = self.overlay(
                        image=image, 
                        watermark_name=watermark_name, 
                        position_x=position_x, 
                        position_y=position_y, 
                        )
        elif watermark_mode == '1':   # 'concatenate'
            result = self.concatenate(
                            image=image, 
                            watermark_name=watermark_name, 
                            )
        else:
            # 随机选择并调用一个函数
            chosen_mode = random.choice(['1', '2']) 
            result = self.add(
                         image=image,
                         watermark_name=watermark_name, 
                         watermark_mode=chosen_mode,
                         position_x=position_x, 
                         position_y=position_y, 
                         )
        return result
        
        
    def overlay(self, 
                image, 
                watermark_name=None, 
                position_x=None, 
                position_y=None,
                ): 

        # 叠加模式     
        if watermark_name and watermark_name in self.watermark_2 and self.watermark_2[watermark_name]:
            logo_image_resized = self.watermark_2[watermark_name]
            # logo_image = self.watermark_2[watermark_name]
            # new_width = image.width // 4
            # new_height = int(logo_image.height * new_width / logo_image.width)
            # logo_image_resized = logo_image.resize((new_width, new_height), )
            # 创建一个新的透明图层,尺寸与原始图像相同
            watermark_background = Image.new('RGBA', image.size, (0, 0, 0, 0))
            watermark_background.paste(image, (0, 0))
            # 将 "AIGC" 图像粘贴到文字水印图层上
            if position_x is None:
                position_x = 0
            if position_y is None:
                position_y = image.height - logo_image_resized.height
            AIGC_position = (position_x, position_y) 
            watermark_background.paste(logo_image_resized, AIGC_position, logo_image_resized)
            
            return watermark_background.convert('RGB')       
        else:
            print("Please check watermark file!")
            return image
        
        
    def concatenate(self, 
                    image, 
                    watermark_name=None, 
                    ):           

        # 拼接模式
        if watermark_name and watermark_name in self.watermark_1 and self.watermark_1[watermark_name]:
            logo_image = self.watermark_1[watermark_name]
            new_width = image.width
            new_height = int(logo_image.height * new_width / logo_image.width)
            logo_image_resized = logo_image.resize((new_width, new_height), )
            # 创建一个新的透明图层,尺寸与原始图像相同
            # watermark_background = Image.new('RGBA', image.size, (0, 0, 0, 0))
            watermark_background = Image.new('RGB', (image.width, image.height + new_height))
            watermark_background.paste(image, (0, 0))
            # 将 "AIGC" 图像粘贴到文字水印图层上
            AIGC_position = (0, image.height) 
            # watermark_background.paste(logo_image_resized, AIGC_position, logo_image_resized)
            watermark_background.paste(logo_image_resized, AIGC_position)
            
            return watermark_background.convert('RGB')       
        else:
            print("Please check watermark file!")
            return image
 

      
# 使用示例  
if __name__ == "__main__":
    wm = WaterMark(watermark_folder="./watermarks",)
    image = Image.open("image.png", )
    watermarked_image = wm.add(image=image,
                               watermark_name="xxx_aigc", 
                               watermark_mode='2',
                               position_x=None, 
                               position_y=None, 
                               )
    # 保存结果
    watermarked_image.save("watermarked_image.jpg")