写文章的时候可以设置是否添加水印。可是,有些图片可能想加水印,有些不想加水印,该怎么办呢?

配置环境

python3 + pillow

pip3 install pillow

引入库

from PIL import Image, ImageSequence
import os
import random

效果预览:

使用方法:

  1. 在脚本同目录下添加水印图片 logo.png
  2. 创建目录 input 并在放入要添加水印的图片
  3. 创建目录 output 执行脚本 addlogo.py
  4. 结果输出在 output 文件夹下

实现原理

水印图片采集:

先读取水印图片的像素点信息和大小信息。去除透明度为0的像素,并修改透明度像素信息。

img_logo = Image.open("logo.png")
img_logo_width, img_logo_height = img_logo.size
img_logo_pixels = dict()
for w in range(img_logo_width):
for h in range(img_logo_height):
c = img_logo.getpixel((w,h))
if c!=(0, 0, 0, 0):
img_logo_pixels[(w, h)] = c[:3]+(125,)

混合颜色:

对每一个像素点采取颜色混合,其中c1是源图片的像素点信息(r,g,b,a),c2是logo图片像素点的信息。混合算法如下:

def blendPixel(c1,c2):
a1=256-c2[3]
a2=c2[3]-(a1*c2[3])/256.0
a=a1+a2
c=(int((a1*c1[0] + a2*c2[0])/a), int((a1*c1[1] + a2*c2[1])/a), int((a1*c1[2] + a2*c2[2])/a),int(a))
return c

处理源 Image 对象:

随机一个位置开始处理像素,具体代码参考如下。

def dealOneImage(image,offX=None,offY=None):
w, h = image.size
offX = offX if offX else random.random();
offY = offY if offY else random.random();
#如果图片尺寸小于水印图片,不加水印
if w>=img_logo_width and h>=img_logo_height:
top = int((w - img_logo_width)*offX)
left = int((h - img_logo_height)*offY)
for p, c in img_logo_pixels.items():
p_x = (p[0]+top)
p_y = (p[1]+left)
image_c = image.getpixel((p_x,p_y))
if(isinstance(image_c, tuple) and len(image_c)>2):
image.putpixel((p_x, p_y), blendPixel(image_c,c))
return image;

处理单个文件:

对于 gif 文件先拆成一张一张图片,在图片上添加水印,最后再合成 gif 。对于其他格式的图片文件可以多添加几个水印。最后输出保存到 output 文件夹下。

def dealOneFile(filePath):
img_orign = Image.open(filePath)
_,file_type = os.path.splitext(filePath)
basename = os.path.basename(filePath)
if file_type == '.gif':
sequence = [];
offX=random.random()
offY=random.random()
for f in ImageSequence.Iterator(img_orign):
if len(sequence) % 2 == 0:
offX=random.random()
offY=random.random()
sequence.append(dealOneImage(f.convert(),offX,offY))
sequence[0].save(f'./output/{basename}', save_all=True, append_images=sequence[1:])
else:
image_out = (dealOneImage(img_orign))
for x in range(1):
image_out = (dealOneImage(image_out))
image_out.save(f'./output/{basename}')

处理目录:

对当前目录下的文件做一个筛选,只选取图片格式的文件。

def dealSrc(srcDir):
picFiles = [os.path.join(srcDir,fn) for fn in os.listdir(srcDir) if fn.endswith(('.gif', '.jpg', '.png','.jpeg'))]
for filePath in picFiles:
dealOneFile(filePath)

小结

添加水印主要用了 python3 中的 pillow 库来实现。 首先是读取 logo 图片信息,接着在随机一个位置添加混合后的像素点信息,最后再保存起来。

其中,对于 gif 文件的处理是拆帧,再添加水印,最后再组合成一个 gif。这个只能对应比较小的 gif 文件处理,如果有更好的方法欢迎留言交流分享!


本文仅供个人学习交流使用,请勿用于其他用途!


参考资料

python 实现图片批量加入水印!pillow 入门实战!的更多相关文章

  1. python爬虫-图片批量下载

    # 爬起摄图网的图片批量下载# coding:utf-8 import requests from bs4 import BeautifulSoup from scipy.misc import im ...

  2. python对图片批量命名

    深度学习中经常会有批量对图片进行重命名,从网上看到的资料整理一下,方便以后查看. import os class BatchRename(): ''' 批量重命名文件夹中的图片文件 ''' def _ ...

  3. 用python给图片添加半透明水印

    # coding:utf-8 from PIL import Image, ImageDraw, ImageFont def add_text_to_image(image, text): font ...

  4. python 工具 图片批量合并

    注:代码两处设置 region = (4,3,x-3,y-5) 目的是crop剪去图片的白边,这个可以视情况改变 图片需要命名为   x_1.png   .....这样的格式 #encoding=ut ...

  5. python 图片格式转换png转jpg,如何利用python给图片添加半透明水印

    from PIL import Imageim = Image.open(r'd:\test2.png')r, g, b, a = im.split()im = Image.merge("R ...

  6. Python实用案例,Python脚本,Python实现批量加水印

    往期回顾 Python实现自动监测Github项目并打开网页 Python实现文件自动归类 Python实现帮你选择双色球号码 Python实现每日更换"必应图片"为"桌 ...

  7. [2015.07.27]万峰图片批量处理专家 v8.6

    万峰图片批量处理专家,界面简洁易用,功能强大实用.支持多种处理任务同时按顺序执行,真正的批量图片,批量效果处理.支持图片批量自定义的放大缩小,旋转或者翻转,支持图片格式批量转换.支持图片批量文字水印, ...

  8. 10 行 Python 代码,批量压缩图片 500 张,简直太强大了

    本文原创并首发于公众号[Python猫],未经授权,请勿转载. 原文地址:https://mp.weixin.qq.com/s/5hpFDgjCpfb0O1Jg-ycACw 熟悉 "Pyth ...

  9. 如何用python裁剪图片

    如何使用python裁剪图片 如上图所示,这是一张包含了各类象棋棋子的图片.我们需要将其中每一个棋子都裁剪出来,此时可以利用python的 PIL库 实现. 一. 安装PIL库 如果此前没有安装过PI ...

随机推荐

  1. java秀发入门到优雅秃头路线导航【教学视频+博客+书籍整理】

    目录 一.Java基础 二.关于JavaWeb基础 三.关于数据库 四.关于ssm框架 五.关于数据结构与算法 六.关于开发工具idea 七.关于项目管理工具Mawen.Git.SVN.Gradle. ...

  2. django-模板之URL标签(五)

    book/views.py from django.shortcuts import render def index(request): return render(request,"in ...

  3. virtual与override的使用

    在函数的声明中,当有“virtual”修饰的时候,和没有virtual有什么区别呢?最重要的一点就是调用实例的函数是在编译的时候确定还是在运行的时候确定,virtual函数是在运行的时候来确定具体调用 ...

  4. SVM详细笔记及总结

    本文精品,如有疑问欢迎留言or微信咨询:523331232

  5. SpringBootCLI 命令行工具

    Spring Boot CLI 是用于快速开发 Spring 应用的命令行工具.用来运行 Groovy (与 Java 风格类似)脚本. spring-cli 似乎不是可以各种diy spring-b ...

  6. webPack 4.0的零基础学习

    webPack 也更新到了4.0阶段,今天看了一下官网,总结一下,零基础的学习路径吧. (1)首先需要下载 webPake和webpack cli npm install webpack webpac ...

  7. Python3爬虫(3)_urllib.error

    注:参照https://blog.csdn.net/c406495762/article/details/59488464 Learn_ERROR: urllib.error可以接收有urllib.r ...

  8. [ASP.NET Core 3框架揭秘] 依赖注入[5]: 利用容器提供服务

    毫不夸张地说,整个ASP.NET Core框架是建立在依赖注入框架之上的.ASP.NET Core应用在启动时构建管道以及利用该管道处理每个请求过程中使用到的服务对象均来源于依赖注入容器.该依赖注入容 ...

  9. zookeeper集群搭建2.7

    http://blog.csdn.net/uq_jin/article/details/51513307

  10. CHRONY 时间服务器

    时间同步服务chrony ntp network time Protocol之前使用的同步协议 chrony ntp协议的实现,兼容网络中的ntp服务(centos7之后就不再使用ntp,转而使用ch ...