使用Python PIL 给图片添加水印

2018-09-04 1 条评论 559 次阅读 25 人点赞

我们做网站,做公众号经常会使用到很多图片,很多图片是我们自己原创的。为了不让人盗图,我们常做的操作是加水印。当然公众号可以打官方的水印,wordpress网站可以用一些插件来实现打水印的目的。如果不使用这两种方式,我们可能会使用PS等图片编辑软件来添加水印,但是感觉为了打个水印打开这些软件似乎让人心累(谁让咱这么懒呢~),所以这里给大家用Python实现这个功能,下来也就20行代码不到。先来看看水印的效果:

这里水印分成文字水印和图片水印,这里首先介绍文字水印。当然完成这一切的前提是你安装了Python的PIL库(或者Pillow也是可以的)。

1.文字水印

话不多说,直接上代码:

from PIL import Image,ImageDraw,ImageFont

image = Image.open('lifeistoshort.jpg')
# 打开要加水印的图片
text=input('输入你的水印文字:\n')
# 提示要打水印的文字
font=ImageFont.truetype('C:\Windows\Fonts\simhei.ttf',64)
# 获得一个字体,你也可以自己下载相应字体,第二个值是字体大小
layer=image.convert('RGBA')
# 将图片转换为RGBA图片
text_overlay=Image.new('RGBA',layer.size)
# 依照目标图片大小生成一张新的图片 参数[模式,尺寸,颜色(默认为0)]
image_draw=ImageDraw.Draw(text_overlay)
# 画图
text_size_x,text_size_y=image_draw.textsize(text,font=font)
# 获得字体大小,textsize(text, font=None)
text_xy=(layer.size[0]-text_size_x,layer.size[1]-text_size_y)
# 设置文本位置 此处是右下角显示
image_draw.text(text_xy, text, font=font, fill=(0, 0, 0, 85))
# 设置文字,位置,字体,颜色和透明度
marked_img=Image.alpha_composite(layer,text_overlay)
# 将水印打到原图片上生成新的图片
marked_img.save('qingwei_after.png')
# 保存图片
marked_img.show()
# 显示图片(这里是生成一个临时文件,必须关闭图片 这段py代码才算结束)

对于水印的字体、颜色、文字等设置相信你看了注释也知道在哪里调整,例如对于位置的调节:

text_xy=(layer.size[0]-text_size_x,layer.size[1]-text_size_y)
# 设置文本位置 此处是右下角显示

text_xy = (layer.size[0]//2-text_size_x//2, layer.size[1]-text_size_y)
# 设置文本位置 此处是下方居中显示

text_xy = (0, layer.size[1]-text_size_y)
# 设置文本位置 此处是左下角下角显示

text_xy=(layer.size[0]-text_size_x,0)
# 设置文本位置 此处是右上角显示

text_xy=(0,0)
# 设置文本位置 此处是左上角角显示

text_xy = (layer.size[0]//2-text_size_x//2, layer.size[1]//2-text_size_y//2)
# 设置文本位置 此处是居中显示

当然,我们可以改进下,可以循环获得指定目录下所有图片文件,然后批量添加水印,下面是简单改进版代码:

from PIL import Image,ImageDraw,ImageFont
import os


def watermark(text,filename,savepath):
    '''
    给图片加文字水印
    text 水印文字 String
    filename 图片名称 String
    savepath 保存路径 String
    '''
    if not os.path.exists(savepath):
        os.makedirs(savepath)
    # 检查保存文件夹是否存在,如果不存在则生成一个    
    image = Image.open(filename)
    # 打开要加水印的图片
    font=ImageFont.truetype('C:\Windows\Fonts\simhei.ttf',64)
    # 获得一个字体,你也可以自己下载相应字体,第二个值是字体大小
    layer=image.convert('RGBA')
    # 将图片转换为RGBA
    text_overlay=Image.new('RGBA',layer.size)
    # 依照目标图片大小生成一张新的图片 参数[模式,尺寸,颜色(默认为0)]
    image_draw=ImageDraw.Draw(text_overlay)
    # 画图
    text_size_x,text_size_y=image_draw.textsize(text,font=font)
    # 获得字体大小,textsize(text, font=None)
    text_xy=(layer.size[0]-text_size_x,layer.size[1]-text_size_y)
    # 设置文本位置 此处是右下角显示
    image_draw.text(text_xy, text, font=font, fill=(0, 0, 0, 85))
    # 设置文字,位置,字体,颜色和透明度
    marked_img=Image.alpha_composite(layer,text_overlay)
    # 将水印打到原图片上生成新的图片
    marked_img.save(savepath+'\\'+filename[filename.rfind("\\")+1:filename.rfind(".")]+".png")
    # 保存图片


def all_path(dirname, filters):
    '''
    获取路径下所有文件名称(完整路径)
    dirname 路径名 String
    filters 过滤文件类型 Array
    '''
    result = []  # 所有的文件

    for maindir, subdir, file_name_list in os.walk(dirname):
        # maindir 当前主目录
        # subdir 当前主目录下的所有目录
        # file_name_list 当前主目录下的所有文件
        for filename in file_name_list:
            apath = os.path.join(maindir, filename)  # 合并成一个完整路径
            ext = os.path.splitext(apath)[1]  # 获取文件后缀 [0]获取的是除了文件名以外的内容

            if ext in filters:
                result.append(apath)

    return result


filters = [".jpg", ".jpeg", ".png"]  # 设置过滤后的文件类型
path = all_path("D:\mytest", filters)
text = input('输入你的水印文字:\n')
for name in path:
    watermark(text,name, "D:\\watermark")

print('Done!')

 

2.图片水印

这个就更简单了,也就十行代码左右,代码如下:

from PIL import Image

image = Image.open('lifeistoshort.jpg')
# 打开等待加水印的图片
watermark = Image.open('qrcode.jpg')
# 打开水印图片
factor = 0.5
# 如果觉得水印图片太大,可以缩放,这里缩放比例为50%
watermark = watermark.resize(
    tuple(map(lambda x: int(x * factor), watermark.size)))
# 缩放图片
layer=Image.new('RGBA',image.size)
# 生成一个新的layer
layer.paste(watermark,(image.size[0]-watermark.size[0],
    image.size[1]-watermark.size[1]))
# 把水印打到新的layer上去,后面参数是水印位置,此处是右下角    
marked_img=Image.composite(layer,image,layer)
# 添加水印
# marked_img.show()# 打开生成的图片(缓存图片)
marked_img.save('maked_lifeistoshort_1.jpg')
# 保存图片

当然,我们依旧来一个批量打水印的版本,代码如下:

from PIL import Image
import os

def watermark(mark, path, savepath):
    ''' 
    给图片加文字水印
    mark 水印文字 String 
    path 图片名称 String 
    savepath 保存路径 String 
    '''
    image = Image.open(path)
    # 打开等待加水印的图片
    watermark = Image.open(mark)
    # 打开水印图片
    factor = 0.5
    # 如果觉得水印图片太大,可以缩放,这里缩放比例为50%
    watermark = watermark.resize(
        tuple(map(lambda x: int(x * factor), watermark.size)))
    # 缩放图片
    layer=Image.new('RGBA',image.size)
    # 生成一个新的layer
    layer.paste(watermark,(image.size[0]-watermark.size[0],
        image.size[1]-watermark.size[1]))
    # 把水印打到新的layer上去,后面参数是水印位置,此处是右下角
    # 更多位置参考上面的代码    
    marked_img=Image.composite(layer,image,layer)
    # 添加水印
    # marked_img.show()# 打开生成的图片(缓存图片)
    marked_img.save(savepath+'\\'+path[path.rfind("\\")+ 1:])
    # 保存图片


def all_path(dirname, filters):
    '''
    获取路径下所有文件名称(完整路径)
    dirname 路径名 String
    filters 过滤文件类型 Array
    '''
    result = []  # 所有的文件

    for maindir, subdir, file_name_list in os.walk(dirname):
        # maindir 当前主目录
        # subdir 当前主目录下的所有目录
        # file_name_list 当前主目录下的所有文件
        for filename in file_name_list:
            apath = os.path.join(maindir, filename)  # 合并成一个完整路径
            ext = os.path.splitext(apath)[1]  # 获取文件后缀 [0]获取的是除了文件名以外的内容

            if ext in filters:
                result.append(apath)

    return result


filters = [".jpg", ".jpeg", ".png"]  # 设置过滤后的文件类型
path = all_path("D:\mytest", filters)
mark='qrcode.jpg'
for name in path:
    watermark(mark, name, "D:\\watermark")
print('Done!')

有了这些代码你要做的只是把图片和水印放到相应位置,让后打开你的命令行,Python 一下,水印就轻松打上了,是不是很爽。水平有限,请多多指教~

人生苦短,我用Python

 

喜欢这篇文章的话可以扫描下方二维码支持我  :mrgreen: 《MySQL优化SQL查询语句的30条建议》

Kiwi

Valar Morghulis

文章评论(1)

  • 取昵称好麻烦

    可以,如果加上图形界面就更好了 :biggrin:

    2018-09-13