【Python】批量給圖片增加水印工具

鄭立賽發表於2021-12-01

背景

最近有一些圖片需要增加水印,找了一圈也沒看見比較好的工具,又不想用破解的PS,乾脆自己做了一個GUI工具,有需要的同學自取

功能

  • 支援水印預覽
  • 自定義水印文字內容
  • 支援行楷和微軟雅黑兩種字型
  • 支援自定義字號
  • 支援自定義水印顏色
  • 支援自定義水印間距
  • 支援自定義水印透明度
  • 支援自定義水印旋轉角度
  • 支援批量給圖片增加水印
  • 僅支援Windows平臺(用到了windows上的字型)

預覽

使用方式

方法一:執行Python指令碼。

電腦上需要安裝python3執行環境

# 安裝依賴包
pip install pillow pysimplegui
# 將下面的原始碼儲存為: image_watermark_tool.py
python image_watermark_tool.py

方法二:直接下載exe檔案,雙擊執行即可。

連結: https://pan.baidu.com/s/1veoNlDJOecq7bw0rQB-FYg
提取碼: b9pe

exe程式由下面的原始碼打包而成

pyinstaller -F -w image_watermark_tool.py

原始碼

# author zhenglisai
from PIL import Image, ImageDraw, ImageFont
import PySimpleGUI as sg
import os
from io import BytesIO
import base64
import traceback


def add_watermark(image, msg, font, font_size, color, distance, transparency, angle):
    if font == "xingkai":
        font_name = "C:\\WINDOWS\\Fonts\\STXINGKA.TTF"
    else:
        font_name = "C:\\WINDOWS\\Fonts\\msyh.ttc"
    font = ImageFont.truetype(font_name, int(font_size))
    if color == "" or color == "None":
        r = 0
        g = 0
        b = 0
    else:
        color = color.replace("#", "0x")
        color = int(color, base=16) if isinstance(color, str) else color
        r = (color >> 16) & 0xff
        g = (color >> 8) & 0xff
        b = color & 0xff
    background = Image.new('RGBA', (image.size[0] * 3, image.size[1] * 3), (0, 0, 0, 0))
    background.paste(image, image.size)
    font_len = len(msg)
    rgba_image = background.convert('RGBA')
    text_overlay = Image.new('RGBA', rgba_image.size, (255, 255, 255, 0))
    image_draw = ImageDraw.Draw(text_overlay)
    for i in range(0, rgba_image.size[0], font_len * 40 + int(distance)):
        for j in range(0, rgba_image.size[1], int(distance)):
            image_draw.text((i, j), msg, font=font, fill=(r, g, b, int(transparency)))
    text_overlay = text_overlay.rotate(int(angle))
    image_result = Image.alpha_composite(rgba_image, text_overlay)
    image_result = image_result.crop((image.size[0], image.size[1], image.size[0] * 2, image.size[1] * 2))
    return image_result


frame = [
        [sg.Text("水印"), sg.InputText("鄭立賽", key="text", enable_events=True)],
        [sg.Text("字型"), sg.Radio("行楷", "font", default=True, key="xingkai", enable_events=True), sg.Radio("微軟雅黑", "font", key="yahei", enable_events=True)],
        [sg.Text("字號"), sg.Slider(range=(1, 100), default_value=36, key="font_size", orientation='horizontal', enable_events=True)],
        [sg.Button("選擇水印顏色", button_type=sg.BUTTON_TYPE_COLOR_CHOOSER, target="color"),sg.InputText("#000000", enable_events=True, key="color", readonly=True, size=(10, 10))],
        [sg.Text("間距"), sg.Slider(range=(1, 500), default_value=200, key="distance", orientation='horizontal', enable_events=True)],
        [sg.Text("透明度"), sg.Slider(range=(0, 255), default_value=50, key="transparency", orientation='horizontal', enable_events=True)],
        [sg.Text("角度"), sg.Slider(range=(-90, 90), default_value=45, key="angle", orientation='horizontal', enable_events=True)],
        [sg.Text("使用說明", text_color="red")],
        [sg.Text("第一步:調整引數,預覽水印")],
        [sg.Text("第二部:點選下方選擇圖片")],
        [sg.Button("開啟圖片", key="open_image")],
        [sg.Text("處理進度"), sg.ProgressBar(100, size=(30, 10), orientation="h", key="progress")]
    ]
frame_image = [
    [sg.Image(key="image"), sg.Sizer(640, 480)]
]

layout = [
    [sg.Frame(title="引數", layout=frame), sg.Frame(title="效果預覽", layout=frame_image, element_justification="center")]
]
default_windows_size = (800, 480)
window = sg.Window("批量新增水印工具",
                   layout,
                   default_element_size=(40, 1),
                   grab_anywhere=True,
                   size=default_windows_size,
                   resizable=True,
                   finalize=True,
                   enable_close_attempted_event=True
                   )

while True:
    try:
        event, value = window.read()
        if event == sg.WIN_CLOSED:
            break
        if event == "open_image":
            image_path_list = sg.popup_get_file("選擇圖片",
                                           no_window=True,
                                           multiple_files=True
                                           )
            source_image_path = os.path.sep.join(image_path_list[0].split("/")[:-1])
            result_path = os.path.join(source_image_path, "watermark")
            if not os.path.exists(result_path):
                os.mkdir(result_path)
            image_count = len(image_path_list)
            text = value["text"]
            font_size = value["font_size"]
            distance = value["distance"]
            transparency = value["transparency"]
            angle = value["angle"]
            color = value["color"]
            progress_bar = window["progress"]
            count = 1
            total = len(image_path_list)
            for image_path in image_path_list:
                image_name = image_path.split("/")[-1].split(".")[0]
                image_source = Image.open(image_path)
                if value["yahei"]:
                    font = "yahei"
                else:
                    font = "xingkai"
                image_result = add_watermark(image_source, text, font, font_size, color, distance, transparency, angle)
                image_result_path = os.path.join(result_path, "%s.png" % image_name)
                image_result.save(image_result_path)
                buffered = BytesIO()
                image_result.save(buffered, format="PNG")
                data = base64.b64encode(buffered.getvalue())
                window["image"].update(data=data)
                progress_bar.UpdateBar(current_count=count, max=total)
                count += 1
            sg.popup_ok('%s張水印圖片已儲存在: %s' % (image_count, result_path))
        if event in ["angle", "transparency", "distance", "yahei", "xingkai", "font_size", "text", "color"]:
            image_demo = Image.new('RGBA', (640, 480), (0, 0, 0, 0))
            if value["yahei"]:
                font = "yahei"
            else:
                font = "xingkai"
            image_result = add_watermark(image_demo, value["text"], font, value["font_size"], value["color"], value["distance"], value["transparency"], value["angle"])
            buffered = BytesIO()
            image_result.save(buffered, format="PNG")
            data = base64.b64encode(buffered.getvalue())
            window["image"].update(data=data)
    except:
        sg.Print(traceback.format_exc())
window.close()

相關文章