为了成批地给图像增加水印,我们这里用到了枕头模块。它的英文名为pillow。安装它的方式为用cmd命令打开DOS提示符窗口,然后输入pip install pillow即可。就像下面这样:
python安装pillow模块方法安装好了pillow模块后,就能使用里面的类或者子模块等了。为了能给图片增加水印,我们需要导入 Image类 、ImageFont类、ImageDraw类、ImageSequence类。用下面的命令即可完成这个任务:
from PIL import Image,ImageFont,ImageDraw,ImageSequence
上面导入的Image是一个类。它有open方法能打开一张图片,加载到内存中。然后我们就能对这张图片进行各种处理了。下面的代码就能打开一张在c盘的名为风火轮编程的图片,并且返回im,以用来引用这张加载到内存中的图片。
im = Image.open('c:/风火轮编程.png')
Image类还有new方法能新建一张在内存中的图片。如下面的代码:
im = Image.new("RGBA",(100,100),color=(255,0,0))
它能新建一张100x100像素的RGBA模式的红色图片。当然,我们把它命名为im。在new命令中,第一个参数“RGBA”表示新建的图形的模式是RGBA模式。第二个参数表示图形的宽度和高度。第三个参数color参数。想必地球人都知道,这是颜色的意思。这里是指定图像的颜色为红色。它用的是三元组(255,0,0)表示的。这是RGB即红绿蓝三元色表示法。由于新建的图像为RGBA模式,所以其实这张图片还有一个通道,用来描述每个像素的透明度的。如果没有写,则默认为每个像素都是完全不透明的。在A通道中0表示完全透明,255表示完全不透明,所以上面的生成的图像每个像素值最终都是(255,0,0,255)。当然我们也可以指定A通道的值。把命令写成下面这样:
im = Image.new("RGBA",(100,100),color=(255,0,0,127))
那么im就是一张红色半透明的在内存中的图像了。如果不太清楚图像的三元色RGB(红绿蓝)表示法,请查阅相关文档。这里不在赘述。刚才建立的这张图片是在内存中。如果需要把它保存在磁盘中,那么用im的save方法,在小括号里写上文件名即可。示例代码为:
im.save('李兴球Python的半透明图像.png')
mageFont是用来新建字体对象的,这样在写的时候就能描述字体的大小和字体类型。如代码,myfont = ImageFont.truetype("msyh.ttf", 12),就能新建一个字体为微软雅黑,字号为12号的字体对象。
ImageDraw是用来在图像上建立绘画层的一个类。实例化它的对象后,就能在这个对象上做图。可以在上面画圆圈,写字等等。假设im对象是加载到内存中的图像,那么draw = ImageDraw.Draw(im)就能新建绘画层。这样用下面的代码:
draw.text(( 10, 10), '李兴球Python', font=myfont,fill='red'))
就能在im图像上坐标为(10,10)上写上红色的,字体为myfont的字了。注意坐标是以图像的右上角为原点的。
我们还需要知道ImageSequence这个类的用途。它可以用来迭代图像中的每帧。所谓帧就是快速显示的一张图片。在gif图像或电影视频中,是有很多帧的,每帧图像可能显示的时间为0.1秒。那么每1秒就能显示10张图。这就是帧率,也就是fps为10。我们把gif图像打开,迭代每一张帧图像,然后给每一张图像用draw的写字命令写上文字说明。最后把所有的帧都合成为新的一张gif图像。这就是给gif图加水印的全过程。即拆帧,在帧上写字,合帧。下面的代码就能迭代每一帧:
for frame in ImageSequence.Iterator(im):
print(frame) # 打印这一帧,当然也可以保存在磁盘
上面的代码迭代了每一帧,当把每一帧图像都修改完后。就要把它们合起来以形成gif文件。如何合帧?pillow模块的图像对象有save方法。它有append_images这个参数。寓意为添加的图像们。这可以指定一个帧列表。加上其它的参数,就能生成gif图片了。
下面就是给gif添加文字水印的函数:
def watermark_on_gif(in_gif,out_gif,text='scratch8'):
"""本函数给gif动图加水印"""
frames = []
myfont = ImageFont.truetype("msyh.ttf", 12) # 加载字体对象
im = Image.open(in_gif) # 打开gif图形
water_im = Image.new("RGBA", im.size) # 新建RGBA模式的水印图
draw = ImageDraw.Draw(water_im) # 新建绘画层
draw.text(( 10, 10), text, font=myfont,fill='red')
for frame in ImageSequence.Iterator(im): # 迭代每一帧
frame = frame.convert("RGBA") # 转换成RGBA模式
frame.paste(water_im,None,water_mask) # 把水印粘贴到frame
frames.append(frame) # 加到列表中
newgif = frames[0] # 第一帧
# quality参数为质量,duration为每幅图像播放的毫秒时间
newgif.save(out_gif,save_all=True,
append_images=frames[1:],quality=85,duration=100)
im.close()
由于gif图中的每一帧并不是RGBA模式,所以在上面的for循环中把frame转换成了RGBA模式。然后把water_im粘贴到了frame上。关于如何调用这个函数就不必要说了吧。完整的示例代码在本人的lixingqiu.com博客上有,请自行搜索Python给gif图片加文字水印就能找到这篇文章的全部示例源代码。