专栏首页白玉无冰python 实现图片批量加入水印!pillow 入门实战!

python 实现图片批量加入水印!pillow 入门实战!

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

配置环境

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 文件处理,如果有更好的方法欢迎留言交流分享!

本文使用图片素材来自网络!版权归原作者所有,如有侵权还请联系!

点击“https://github.com/baiyuwubing/python-exercise/tree/master/py3/add_logo”查看完整代码

本文分享自微信公众号 - 白玉无冰(lamyoung-com),作者:lamyoung

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript | 如何反转(reverse)数组(array)【译】

    在javascript如何反转数组呢?如果想反转一个数组,可以使用array的方法reverse()⏪。接下来提供了几种方法,可以实现这个功能。你要思考的是你何...

    白玉无冰
  • 史上最全面的正则表达式教程,读完就能彻底理解!支持python , js , php 等多种语言在线练习!代码生成!

    白玉无冰
  • 物理挖洞之 3D 效果!

    另一位群友 @云谷 在思路指导下,迅速写了一个版本,传到群里给大家分享,再次感谢!

    白玉无冰
  • js中获取时间new date()的用法 原

    得到的结果:1280977330000 注意:这里得到的结果将后三位(毫秒)转换成了000显示,使用时可能会出现问题。例如动态添加页面元素id的时候,不建议使用...

    山河木马
  • 【已解决】CommandLine 获取程序执行所在的目录

    我利用 CommandLine 写了一个命令行程序 但是不知道怎么获取这个程序执行所在的目录。

    君赏
  • Linux 删除文件夹和文件的命令

    -r 就是向下递归,不管有多少级目录,一并删除 -f 就是直接强行删除,不作任何提示的意思

    周小董
  • CSS3实现图片放大旋转

    py3study
  • python 批量修改密码

    py3study
  • 【机器学习】--SVM从初始到应用

    SVM在2012年前还是很牛逼的,但是12年之后神经网络更牛逼些,但我们还是很有必要了解SVM的。

    LhWorld哥陪你聊算法
  • Python运维之psutil模块

    最近开始学习Python自动化运维,特记下笔记。 学习中使用的系统是Kali Linux2017.2,Python版本为2.7.14+ 因为在KALI里面没有自...

    py3study

扫码关注云+社区

领取腾讯云代金券