【Python】给动态图片加水印

news2024/9/25 19:22:07

文章目录

  • 原文:https://blog.c12th.cn/archives/35.html
  • 前言
  • 部分代码
    • ini文件
    • CMD
  • 完整代码
    • 使用教程(打包整理后文件)
    • 注意事项
  • 最后

原文:https://blog.c12th.cn/archives/35.html

前言

之前 图片加水印 是对于静态图片,而现在这个是对动态图片 (.gif) 加水印。


请添加图片描述

原图

请添加图片描述

加水印后


部分代码

def add_watermark_to_gif(gif_path, watermark_text, output_path, font_path, font_color, font_size, position):
    # 打开GIF图像
    with Image.open(gif_path) as gif:
        # 检查图像是否为GIF动画
        if gif.is_animated:
            # 获取GIF的帧数和持续时间
            frames = []
            durations = []
            for i in range(gif.n_frames):
                gif.seek(i)
                frame = gif.copy().convert("RGBA")  # 确保帧是RGBA模式
                frames.append(frame)
                durations.append(gif.info['duration'])

            # 为每一帧添加水印
            watermarked_frames = []
            for frame in frames:
                draw = ImageDraw.Draw(frame)
                # 加载字体
                font = ImageFont.truetype(font_path, font_size)

                # 在指定位置绘制水印
                draw.text(position, watermark_text, fill=font_color, font=font)
                watermarked_frames.append(frame)

            # 保存带有水印的GIF
            watermarked_gif = frames[0]
            watermarked_gif.save(
                output_path,
                save_all=True,
                append_images=watermarked_frames[1:],
                durations=durations,
                loop=0
            )
        else:
            # 如果GIF不是动画,只需为单帧添加水印
            with Image.open(gif_path) as img:
                img = img.convert("RGBA")  # 确保图像是RGBA模式
                draw = ImageDraw.Draw(img)
                font = ImageFont.truetype(font_path, font_size)
                draw.text(position, watermark_text, fill=font_color, font=font)
                img.save(output_path)

ini文件

def read_config(ini_path):
    config = configparser.ConfigParser()
    config.read(ini_path)

    # 获取ini
    watermark_text = config['diy']['text']
    font_path = config['diy']['path']
    font_color = tuple(map(int, config['diy']['color'].split(',')))
    font_size = int(config['diy']['size'])
    position = tuple(map(int, config['diy']['xy'].split(',')))
    output = config['diy']['out']

    return watermark_text, font_path, font_color, font_size, position, output

    batch_add_watermark_to_gifs('input', 'user.ini')
[diy]
path = STXINGKA.TTF
size = 36
text = @Reverse
color = 0, 255, 255
xy = 50, 50
out = out
# ini备注
path        水印字体路径
size        水印字体大小
text        水印字体
color       水印字体颜色(RGB)
xy          水印位置坐标X,Y
out         处理后的文件路径

CMD

rd /s /q .\out

rd /s /q .\input

mkdir input

先删除 outinput 文件夹,再生成 input 文件夹


完整代码

# 工程:test
# 创建时间:2024/6/24 23:20
# encoding:utf-8

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


def read_config(ini_path):
    config = configparser.ConfigParser()
    config.read(ini_path)

    # 获取ini
    watermark_text = config['diy']['text']
    font_path = config['diy']['path']
    font_color = tuple(map(int, config['diy']['color'].split(',')))
    font_size = int(config['diy']['size'])
    position = tuple(map(int, config['diy']['xy'].split(',')))
    output = config['diy']['out']

    return watermark_text, font_path, font_color, font_size, position, output


def add_watermark_to_gif(gif_path, watermark_text, output_path, font_path, font_color, font_size, position):
    # 打开GIF图像
    with Image.open(gif_path) as gif:
        # 检查图像是否为GIF动画
        if gif.is_animated:
            # 获取GIF的帧数和持续时间
            frames = []
            durations = []
            for i in range(gif.n_frames):
                gif.seek(i)
                frame = gif.copy().convert("RGBA")  # 确保帧是RGBA模式
                frames.append(frame)
                durations.append(gif.info['duration'])

            # 为每一帧添加水印
            watermarked_frames = []
            for frame in frames:
                draw = ImageDraw.Draw(frame)
                # 加载字体
                font = ImageFont.truetype(font_path, font_size)

                # 在指定位置绘制水印
                draw.text(position, watermark_text, fill=font_color, font=font)
                watermarked_frames.append(frame)

            # 保存带有水印的GIF
            watermarked_gif = frames[0]
            watermarked_gif.save(
                output_path,
                save_all=True,
                append_images=watermarked_frames[1:],
                durations=durations,
                loop=0
            )
        else:
            # 如果GIF不是动画,只需为单帧添加水印
            with Image.open(gif_path) as img:
                img = img.convert("RGBA")  # 确保图像是RGBA模式
                draw = ImageDraw.Draw(img)
                font = ImageFont.truetype(font_path, font_size)
                draw.text(position, watermark_text, fill=font_color, font=font)
                img.save(output_path)


def batch_add_watermark_to_gifs(gif_folder, ini_path):
    watermark_text, font_path, font_color, font_size, position, output = read_config(ini_path)

    # 确保输出文件夹存在
    if not os.path.exists(output):
        os.makedirs(output)

    # 遍历GIF文件夹中的所有文件
    for filename in os.listdir(gif_folder):
        if filename.lower().endswith('.gif'):
            input_path = os.path.join(gif_folder, filename)
            output_path = os.path.join(output, filename)
            add_watermark_to_gif(input_path, watermark_text, output_path, font_path, font_color, font_size, position)

        print(f"{filename}")

batch_add_watermark_to_gifs('input', 'user.ini')

print('图片已批量处理完成!')


使用教程(打包整理后文件)

请添加图片描述\

这里的步骤跟 Python日记 - 图片加水印 一致

  1. 打开 user.ini里面的配置可自行修改

  2. 把将要处理的图片全部放到 input 文件夹中

  3. 双击运行 main.exe

  4. 等待窗口运行

  5. 处理后的图片在 out

  6. 双击 删除.bat (这个用于快速清理 inputout 的文件)

注意事项

  1. 图片只支持 gif 格式图片

  2. 如果需要改字体文件,还需要在 user.ini 里修改水印字体路径

path = 水印字体路径

最后

代码已上传到 github 和 gitee

打包整理后文件 蓝奏云 密码:9g98


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2073633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个快速简单的工具来分析SSL/TLS协议数据帧 (C/C++代码实现)

SSL/TLS协议是网络安全通信的基石,它通过在客户端和服务器之间建立一个加密的通道,确保数据传输的安全性和完整性。SSL(Secure Sockets Layer)最初由Netscape公司开发,而TLS(Transport Layer Security&…

Renesa Version Board开发RT-Thread 之UART驱动应用

目录 概述 1 硬件介绍 2 软件配置 2.1 RT-Thread Studio配置参数 2.2 FSP配置MCU 3 RT-Thread中UART的接口介绍 3.1 RT-Thread UART简介 3.2 RT-Thread 下的UART接口 4 UART的应用 4.1 应用功能实现 4.2 源代码文件 5 测试 程序下载地址: RenesaVersio…

Open3D 最小点约束的体素滤波(34)

Open3D 最小点约束的体素滤波(34) 一、算法介绍二、算法流程三、算法代码四、实现效果一、算法介绍 体素滤波可以达到快速减少点云数量的目的,而海量点云往往是需要这一步骤才可以进行后续处理的,比如配准时使用千万级别的原始点云配准显然是不合理的,因此体素滤波是比较重…

Mybatis搭建配置文件基础用法参数传递

背景介绍 Mybatis原是Apache的一个开源项目iBatis 2010碾开发团队转移到谷歌旗下改名为Mybatis Mybatis介绍 Mybatis是一个优秀的数据持久层框架(dao层 数据访问层 数据持久层) Mybatis是对jdbc进行封装,比见面jdbc这手动设置参数,手动映射结果的操作 Mybatis是将jdbc中的…

高变比LLC谐振变换器中“十”字型低匝比平面变压器设计

导语 为了解决高变比LLC谐振变换器的变压器绕组匝数过多、绕组结构复杂这一技术瓶颈背后的核心科学问题,本文提出一种“十”字型低匝比平面变压器,用于高变比LLC谐振变换器。 1.0引言 大数据中心的建设离不开供配电系统—电源设备的建设,为大…

15天速通java基础:java(J2SE)阶段学习总结(数据类型、数组、方法、面向对象、异常处理、容器、流、多线程、网络编程)

有一段时间没有写博客了,我这段时间去学习java了,谁也不会想到,短短两周的时间,我的java学习已经学习了不少东西了,毕竟python这座山也可以去攻java这块玉,对应python那就是基础的大部分内容,不…

吴恩达机器学习课后作业-06支持向量机(SVM)

SVM 线性可分SVM题目绘制决策边界改变C,观察决策边界代码 线性不可分SVM核函数代码 寻找最优C、gamma垃圾邮件过滤 线性可分SVM 题目 数据分布 绘制决策边界 import numpy as np import matplotlib.pyplot as plt import scipy.io as sio from scipy.optimize import minimi…

电子电路学习之二极管-1

特别感谢:B站博主:唐老师讲电赛 工科男孙老师 本文图片出自两位博主视频 再次感谢 1 半导体 1. 本征半导体 (Intrinsic Semiconductor) 定义:本征半导体是指纯净的、不掺杂任何杂质的半导体材料,如硅(Si)…

日本人形机器人仿真环境搭建

机器人 官网在这里 http://ai2001.ifdef.jp/uvc/uvc.html 我们可以下载他们的源码 ODE引擎安装 这个是刚体动力学模拟引擎,我用的是windows,大家可以自己参考着官网来(http://ode.org/wiki/index.php/Manual#Install_and_Use)…

【SpringBoot】自定义spring-boot-starter

目录 定义和目的# 命名规范# 准备阶段# 开发步骤# 一、创建 Starter 项目# 二、导入必要的依赖# 三、编写属性类# 四、自定义业务类# 五、编写自动配置类# 六、编写 spring.factories# ​编辑 七、编写配置提示文件# 八、测试 starter# 测试 starter# 一、导入自…

如何玩转CentOS Linux内核升级?手把手教你内核编译升级至最新版本

文章目录 如何玩转CentOS Linux内核升级?手把手教你内核编译升级至最新版本1 升级环境2 升级需求2.1 升级前的内核版本2.2 升级后的内核版本 3 升级步骤3.1 安装编译环境3.2 更新GCC版本3.2.1 多GCC版本共存3.2.2 永久替换旧的GCC 3.3 下载内核源代码并解压3.4 配置…

《数据结构》(408代码题及应用题)(王道收编真题)

一、线性表 1、线性表的线性表示 分析: “循环”左移,那这个循环就应该是我们需要重点思考的点。先考虑最简单的我们可以设置两个数组,其中一个数组保存的是原数据,另一个初始为空。接着想要实现循环左移就只需要找出相对应的位…

2002-2023年中债国债3年期到期收益率

国债是一种政府发行的债券,它为投资者提供了一种相对安全的投资渠道,因为背后有国家信用的支撑。国债的发行可以帮助政府筹集资金,用于公共支出、基础设施建设、社会福利等项目。国债通常分为两种形式:固定利率国债和浮动利率国债…

PHP 7.4.21 development server 源码泄露漏洞复现

原漏洞地址&#xff1a;https://blog.projectdiscovery.io/php-http-server-source-disclosure/ 版本&#xff1a;PHP<7.4.21 漏洞成因&#xff1a; 通过&#xff1a;PHP -s 开启的内置web服务器存在源码泄露漏洞&#xff0c;可以将PHP文件作为静态代码直接输出源码 POC&…

【区间dp】 P1775 石子合并(弱化版) 题解

题目描述 设有 N ( N ≤ 300 ) N(N \le 300) N(N≤300) 堆石子排成一排&#xff0c;其编号为 1 , 2 , 3 , ⋯ , N 1,2,3,\cdots,N 1,2,3,⋯,N。每堆石子有一定的质量 m i ( m i ≤ 1000 ) m_i\ (m_i \le 1000) mi​ (mi​≤1000)。现在要将这 N N N 堆石子合并成为一堆。每…

20240825 每日AI必读资讯

超6亿&#xff01;文心大模型日调用量半年增长超10倍&#xff0c;AI成百度最强加速引擎 - 文心大模型日调用量超过6亿次&#xff0c;日均处理Tokens文本超1万亿。与23年Q4公布的5000万次日均调用量相比&#xff0c;半年增长超10倍。 - 第二季度&#xff0c;百度云业务营收51亿…

【计算机网络】socket网络编程 --- 实现简易UDP网络程序之字符串回响

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

【北京仁爱堂】脖子歪斜,拉扯疼痛怎么办?规律的生活让痉挛性斜颈的恢复事半功倍!

痉挛性斜颈是一种肌张力障碍性疾病&#xff0c;也是一种让人非常痛苦不堪的疾病&#xff0c;他不仅影响患者的外貌&#xff0c;也会对患者的身体和心理造成双重的打击&#xff0c;严重影响正常的生活&#xff0c;社交和工作。 痉挛性斜颈的病因尚不明确&#xff0c;因为做任何仪…

Java Web —— 第八天(登录功能)

基础登录功能 LoginController 类 RestController //用于处理 HTTP 请求 Slf4j //记录日志 RequestMapping("/login") public class LoginController {Autowiredprivate EmpService empService;PostMappingpublic Result login(RequestBody Emp emp){log.info(&quo…

FFmpeg的入门实践系列六(编程入门之常见处理流程)

欢迎诸位来阅读在下的博文~ 在这里&#xff0c;在下会不定期发表一些浅薄的知识和经验&#xff0c;望诸位能与在下多多交流&#xff0c;共同努力 文章目录 前期博客参考书籍一、FFmpeg常见的处理流程复制编解码器的参数完整代码 二、创建并写入音视频文件三、总结附页 前期博客…