zoukankan      html  css  js  c++  java
  • 【Python】批量给图片增加水印工具

    背景

    最近有一些图片需要增加水印,找了一圈也没看见比较好的工具,又不想用破解的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()
    

    原创作者:郑立赛


    邮箱:zhenglisai@qq.com


    欢迎关注我们的公众号获取最新文章:运维自动化开发


    公众号
    公众号
  • 相关阅读:
    Android优化之软引用和弱引用
    Android中Service与IntentService的使用比较
    Android配置文件,所有权限
    为什么Android手机总是越用越慢?
    Android之安全机制
    JDK8-函数式接口
    JDK8-Java Streams 收集器
    JDK8- java.util.stream 库笔记
    MVVM核心实现代码(简易实现)
    JavaScript小总结
  • 原文地址:https://www.cnblogs.com/zhenglisai/p/15607812.html
Copyright © 2011-2022 走看看