PIL如何批量给图片添加文字水印?

PIL如何批量给图片添加文字水印?

  • 1 简单引入
  • 2 关于PIL
  • 3 本文涉及的PIL的几个类
  • 4 实现原理
  • 5 实现过程
    • 5.1 原始图片
    • 5.2 导入相关模块
    • 5.3 初始化数据
    • 5.4 水印字体设置
    • 5.5 打开原始图片并新建存储对象
    • 5.6 计算图片和水印的大小
    • 5.7 选择性设置水印文字
    • 5.8 绘制文字并设置透明度
    • 5.9 遍历获取图片文件并调用绘制方法
  • 6 完整源码
  • 7 显示效果

1 简单引入

  • 平常我们想给某些图片添加文字水印,方法有很多,也有很多的工具可以方便的进行;
  • 今天主要是对PIL库的应用,结合Python语言批量对图片添加水印;
  • 这里需要注意的是图片的格式,不能为JPG或JPEG,因为这两种格式的图片不支持透明度设置。

2 关于PIL

之前有的文章已经详细介绍过,这里不再赘述了。

  • PILPython的一个图像处理库,支持多种文件格式;
  • PIL提供强大的图像处理和图形处理能力;
  • 可完成对图像的缩放、裁剪、叠加以及图像添加线条、图像和文字等操作。
  • 安装的话,使用以下命令:
pip install Pillow

在这里插入图片描述

3 本文涉及的PIL的几个类

模块或类说明
image模块用于对图像就行处理
ImageDraw2D图像对象
ImageFont存储字体
ImageEnhance图像增强

4 实现原理

本文主要目的是批量对某个文件夹下的图片进行添加水印,原理如下:

  • 对水印内容设置;
  • 使用Image对象的open()方法打开原始图片;
  • 使用Image对象的new()方法新建存储水印图片对象;
  • 使用Image.Draw.Draw对象的text()绘制水印文字;
  • 使用ImageEnhance中的Brightness中的enhance()设置水印透明度。

5 实现过程

5.1 原始图片

  • 我们设置一个原始图片的存储目录,比如:
F:\python_study\image\image01
  • 这个文件夹中存放了多个png格式的图片:
    在这里插入图片描述
  • 这里的一个原始图片为:
    在这里插入图片描述

5.2 导入相关模块

  • 导入需要的几个PIL中的模块或类:
from PIL import Image, ImageDraw, ImageFont, ImageEnhance
import os

5.3 初始化数据

  • 我们这里预想的是,通过用户自己手动输入相关信息,比如图片的存储路径,需要设置的水印文字,通过输入的方式设置水印的位置,设置水印的透明度等;
class TestText():
    def __init__(self):
        super(TestText, self).__init__()
        self.pic_path = input('图片路径:')
        self.pic_text = input('水印文字:')
        self.p_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):'))
        self.a = float(input('水印透明度(0—1之间的1位小数):'))

5.4 水印字体设置

  • 这里我们先看下ImageFont.truetype源码:
def truetype(font=None, size=10, index=0, encoding="", layout_engine=None):
    """
    Load a TrueType or OpenType font from a file or file-like object,
    and create a font object.
    This function loads a font object from the given file or file-like
    object, and creates a font object for a font of the given size.

    Pillow uses FreeType to open font files. On Windows, be aware that FreeType
    will keep the file open as long as the FreeTypeFont object exists. Windows
    limits the number of files that can be open in C at once to 512, so if many
    fonts are opened simultaneously and that limit is approached, an
    ``OSError`` may be thrown, reporting that FreeType "cannot open resource".
    A workaround would be to copy the file(s) into memory, and open that instead.

    This function requires the _imagingft service.

    :param font: A filename or file-like object containing a TrueType font.
                 If the file is not found in this filename, the loader may also
                 search in other directories, such as the :file:`fonts/`
                 directory on Windows or :file:`/Library/Fonts/`,
                 :file:`/System/Library/Fonts/` and :file:`~/Library/Fonts/` on
                 macOS.

    :param size: The requested size, in pixels.
    :param index: Which font face to load (default is first available face).
    :param encoding: Which font encoding to use (default is Unicode). Possible
                     encodings include (see the FreeType documentation for more
                     information):
  • 它的大意就是从系统中的字体库中读取字体;
  • 那我们的系统字体在哪里呢?
  • 系统字体在
C:\Windows\Fonts
  • 如下:
    在这里插入图片描述
  • 我们随便选一个自己喜欢的字体,复制下名字即可:
self.font = ImageFont.truetype("cambriab.ttf", size=35)

5.5 打开原始图片并新建存储对象

  • 打开原始图片,并转换为RGB
image = Image.open(img).convert('RGBA') 
  • 创建绘制对象:
new_img = Image.new('RGBA', image.size, (255, 255, 255, 0))
image_draw = ImageDraw.Draw(new_img)

5.6 计算图片和水印的大小

  • 图片大小:
w, h = image.size  
  • 文字大小:
w1 = self.font.getsize(self.pic_text)[0]  # 获取字体宽度
h1 = self.font.getsize(self.pic_text)[1]  # 获取字体高度

5.7 选择性设置水印文字

  • 通过if语句来实现:
 if self.p_flag == 1:  # 左上角
      location = (0, 0)
 elif self.p_flag == 2:  # 左下角
      location = (0, h - h1)
 elif self.p_flag == 3:  # 右上角
      location = (w - w1, 0)
 elif self.p_flag == 4:  # 右下角
      location = (w - w1, h - h1)
 elif self.p_flag == 5:  # 居中
      location = (h/2, h/2)

5.8 绘制文字并设置透明度

  • 绘制文字:
image_draw.text(location, self.pic_text, font=self.font, fill="blue")
  • 设置透明度
 transparent = new_img.split()[3]
 transparent = ImageEnhance.Brightness(transparent).enhance(self.a)
 new_img.putalpha(transparent)

 Image.alpha_composite(image, new_img).save(img)

5.9 遍历获取图片文件并调用绘制方法

 text_pic = TestText()
    try:
        file_list = os.listdir(text_pic.pic_path)
        for i in range(0, len(file_list)):
            filepath = os.path.join(text_pic.pic_path, file_list[i])  
            if os.path.isfile(filepath): 
                filetype = os.path.splitext(filepath)[1] 
                if filetype == '.png': 
                    text_pic.test_text(filepath) 
                else:
                    print("图片格式有误,无法添加水印,请使用png格式图片")
        print('批量添加水印完成')
    except:
        print('输入的文件路径有误,请检查~~')

6 完整源码

# -*- coding:utf-8 -*-
# 作者:虫无涯
# 日期:2023/11/21 
# 文件名称:test_text_pic.py
# 作用:批量给图片添加文字水印和图片水印
# 联系:VX(NoamaNelson)
# 博客:https://blog.csdn.net/NoamaNelson


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


class TestText():
    def __init__(self):
        super(TestText, self).__init__()
        self.pic_path = input('图片路径:')
        self.pic_text = input('水印文字:')
        self.p_flag = int(input('水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):'))
        self.a = float(input('水印透明度(0—1之间的1位小数):'))

        # 设置字体
        self.font = ImageFont.truetype("cambriab.ttf", size=35)

    # 文字水印
    def test_text(self, img):
        global location
        image = Image.open(img).convert('RGBA') 
        new_img = Image.new('RGBA', image.size, (255, 255, 255, 0)) 
        image_draw = ImageDraw.Draw(new_img) 
        w, h = image.size  # 图片大小
        w1 = self.font.getsize(self.pic_text)[0]  # 字体宽度
        h1 = self.font.getsize(self.pic_text)[1]  # 字体高度

        # 设置水印文字位置
        if self.p_flag == 1:  # 左上角
            location = (0, 0)
        elif self.p_flag == 2:  # 左下角
            location = (0, h - h1)
        elif self.p_flag == 3:  # 右上角
            location = (w - w1, 0)
        elif self.p_flag == 4:  # 右下角
            location = (w - w1, h - h1)
        elif self.p_flag == 5:  # 居中
            location = (h/2, h/2)
        # 绘制文字
        image_draw.text(location, self.pic_text, font=self.font, fill="blue")

        # 设置透明度
        transparent = new_img.split()[3]
        transparent = ImageEnhance.Brightness(transparent).enhance(self.a)
        new_img.putalpha(transparent)

        Image.alpha_composite(image, new_img).save(img)


if __name__ == "__main__":
    text_pic = TestText()
    try:
        file_list = os.listdir(text_pic.pic_path) 
        for i in range(0, len(file_list)): 
            filepath = os.path.join(text_pic.pic_path, file_list[i])
            if os.path.isfile(filepath): 
                filetype = os.path.splitext(filepath)[1] 
                if filetype == '.png': 
                    text_pic.test_text(filepath) 
        print('批量添加水印完成')
    except:
        print('输入的文件路径有误,请检查~~')

7 显示效果

  • 运行过程:
D:\Python37\python.exe F:/python_study/python_project/test_text_pic.py
图片路径:F:\python_study\image\image01
水印文字:@虫无涯
水印位置(1:左上角,2:左下角,3:右上角,4:右下角,5:居中):1
水印透明度(01之间的1位小数):0.5
F:/python_study/python_project/test_text_pic.py:32: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
  w1 = self.font.getsize(self.pic_text)[0]  # 获取字体宽度
F:/python_study/python_project/test_text_pic.py:33: DeprecationWarning: getsize is deprecated and will be removed in Pillow 10 (2023-07-01). Use getbbox or getlength instead.
  h1 = self.font.getsize(self.pic_text)[1]  # 获取字体高度
批量添加水印完成
  • 不同位置的水印效果:
    在这里插入图片描述
  • 居中效果:
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT/GPT4科研实践应用与AI绘图技术及论文高效写作

2023年随着OpenAI开发者大会的召开,最重磅更新当属GPTs,多模态API,未来自定义专属的GPT。微软创始人比尔盖茨称ChatGPT的出现有着重大历史意义,不亚于互联网和个人电脑的问世。360创始人周鸿祎认为未来各行各业如果不能搭上这班车…

高防CDN如何预防攻击?

现在网络攻击事件越来越多,而且愈发凶猛,为了保障互联网业务能稳定正常的运行,市场上出现了很多高防产品,例如高防服务器、高防IP、高防CDN等等。其中究竟高防CDN怎么防攻击,能防哪些攻击?高防CDN如何实现防…

【PostgreSQL】解决PostgreSQL时区(TimeZone)问题

问题描述 最近在使用PostgreSQL中,对行记录进行设置创建时间(created_time)时,出现了设置了now()时间而数据库中写入的数据是不一致的数据。 eg: insert into dept ( created_at, updated_at) VALUES (now(),now())…

结合两个Python小游戏,带你复习while循环、if判断、函数等知识点

💐作者:insist-- 💐个人主页:insist-- 的个人主页 理想主义的花,最终会盛开在浪漫主义的土壤里,我们的热情永远不会熄灭,在现实平凡中,我们终将上岸,阳光万里 ❤️欢迎点…

一文概括AxureRP的优缺点和替代软件

AxureRP是目前流行的设计精美的用户界面和交互软件。AxureRP根据其应用领域提供了一组丰富的UI控制。 Axure是什么软件? Axure是目前流行的设计精美的用户界面和交互软件。Axure已经存在了近十年,让UX设计师轻松了解创建软件原型的细节。作为一种原型设…

nvm管理node版本过程记录

写在前面 今天记录一下windows电脑安装nvm同时使用nvm管理node版本的,为什么写windows版本的呢?因为mac版本的基本上是不需要进行记录的,相对windows的安装是简单很多的,行了废话不多说,我们直接开始 安装nvm nvm下载…

如何使用rclone将腾讯云COS桶中的数据同步到华为云OBS

在多云策略与数据迁移趋势下,企业往往需要将数据在不同云服务提供商之间进行迁移。本文介绍如何使用rclone工具同步腾讯云COS(Cloud Object Storage)桶中的数据到华为云OBS(Object Storage Service)。先决条件是您已经…

Vue Router的使用

Vue.js是一个流行的JavaScript框架,用于开发单页面应用程序。Vue提供了一个强大的路由系统,可以帮助我们管理应用程序中的不同页面。在本文中,我们将详细讲解Vue路由的使用方法。 目录 1. 安装Vue Router2. 创建路由实例3. 配置路由4. 在模板…

六、流量监管、流量整形

流量监管、流量整形 流量监管、流量整形1.1.定义1.2.简单流分类应用场景举例1.3.简单流分类的配置1.4.复杂流分类1.5.复杂流分类在产品中的实现 ————————————————— 流量监管、流量整形 当报文的发送速率大于接收速率,或者下游设备的接口速率小于…

gitlab 实战

一.安装依赖 yum install -y curl policycoreutils-python openssh-server perl 二.安装gitlab yum install gitlab-jh-16.0.3-jh.0.el7.x86_64.rpm 三.修改下面的 vim /etc/gitlab/gitlab.rbexternal_url http://192.168.249.156 四.初始化 gitlab-ctl reconfigure 五.查看状…

SwiftUI 如何动态开始和停止播放永久重复(repeatForever)动画

0. 功能需求 在 SwiftUI 丰富多彩的动画世界中,我们有时希望可以随意开始和停止永久循环(repeatForever)的动画,不过这时往往会产生错误的动画“叠加”效果。 从上图可以看到:虽然我们希望密码输入框背景只在用户输入密码时才发生闪烁,但顶部的密码输入框随着不断输入其…

第一次参加算法比赛是什么感受?

大家好,我是怒码少年小码。 冬日暖阳,好日常在。今天中午在食堂干饭的时候,我的手机📱收到了一条收货信息。 阿?什么玩意儿?我又买啥了? 个败家玩意,我都准备好叨叨我自己&#x…

【数值计算方法】矩阵特征值与特征向量的计算(一):Jacobi 旋转法及其Python实现

文章目录 一、Jacobi 旋转法1. 基本思想2. 计算过程演示3. 注意事项 二、Python实现迭代过程(调试) 矩阵的特征值(eigenvalue)和特征向量(eigenvector)在很多应用中都具有重要的数学和物理意义。Jacobi 旋转…

electron使用electron-builder macOS windows 打包 签名 更新 上架

0. 前言 0.1 项目工程 看清目录结构,以便您阅读后续内容 0.2 参考资料 (1)macOS开发 证书等配置/打包后导出及上架 https://www.jianshu.com/p/c9c71f2f6eac首先需要为Mac App创建App ID: 填写信息如下—Description为"P…

十七、SpringAMQP

目录 一、SpringAMQP的介绍: 二、利用SpringAMQP实现HelloWorld中的基础消息队列功能 1、因为publisher和consumer服务都需要amqp依赖,因此这里把依赖直接放到父工程mq-demo中 2、编写yml文件 3、编写测试类,并进行测试 三、在consumer…

申银万国期货通过ZStack Cube信创超融合一体机打造金融信创平台

信创是数字中国建设的重要组成部分,也是数字经济发展的关键推动力量。作为云基础软件企业,云轴科技ZStack产品矩阵全面覆盖数据中心云基础设施,ZStack信创云首批通过可信云《一云多芯IaaS平台能力要求》先进级,是其中唯一兼容四种…

音视频开发是不是C++开发中最难的细分方向?

音视频开发是不是C开发中最难的细分方向? 是不是最难不敢说(毕竟数据库、Office、 大型游戏可能更难),但确实也已经很难 了。至少对我 这种主要搞web前端的人来说,真的有那种力不从心的感觉。最近很多小伙伴找我,说想要一些音视频…

【微服务】SaaS云智慧工地管理平台源码

智慧工地系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段,实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 一、智慧工地让工程施工智能化 1、内容全面,多维度数…

数字化转型导师坚鹏:数字化时代银行网点厅堂营销5大难点分析

数字化时代银行网点厅堂营销存在以下5大难点: 1、识别难。识别有效的客户比较难,传统的厅堂识别主要依据客户的衣着气质等主管感受,判断客户是否为潜在中高端客户,提供相关服务。大堂经理主管识别与智能化系统识别相结合&#xf…