在实际生产中,用户上传图片是非常常见的行为,无论是做一个相册系统,还是发布文章中带有图片,可以说图片和Web服务是非常紧密的了。但是图片所占用的空间,以及图片的大小等又都是不参差不齐的,同时有些网站的图片在上传之后,可能被其他平台或者开发者采集并且盗用,这个时候,很多人的做法是在图片上传的时候,进行图像压缩、标准化以及添加水印,但是这一套流程往往又比较占用资源,尤其是大量大尺寸的图片产生时。那么在Serverless架构下,是否有一种方法,可以对图像的压缩与水印实现"一条龙"服务,而且不会因为用户量比较多,而影响用户整体体验呢?
Serverless与图像处理
在前言部分说到,传统的图像处理方法,会比较占用资源,让服务器压力比较大,甚至会影响用户体验:
那么我们是否可以通过Serverless架构,实现一个异步处理流程?
所谓的异步处理流程就是,用户直接上传图片到对象存储,直接将图片等资源进行持久化,然后通过对象存储相关的触发器,触发指定函数,函数进行图像压缩以及图像水印等相关处理,再次进行持久化。
以相册系统为例:用户上传图片之后,系统进行压缩以及水印并生成缩略图,存储到对象存储中,当用户浏览图片列表时,展示带有水印的缩略图,可以大大提升加载速度,水印可以看作图像的一种版权保护,当用户点击图片查看原图时,可以为用户展示原始图片。这样既能保证原图的存在,就可以提高浏览列表等的速度,也具备初步的版权保护能力。
图像压缩
图像压缩部分,在这里只用图像的大小作为压缩依据,除此之外还可以对图像的质量进行处理。
单以尺寸进行压缩处理,可以看作是将一个image
对象和宽度传入,通过resize
方法进行大小的调整,实现压缩功能。
def compressImage(image, width):
height = image.size[1] / (image.size[0] / width)
return image.resize((int(width), int(height)))
图像水印
图像水印部分采用的是文字水印,除了文字水印还可以考虑使用图片水印等。
此处为了将水印放在图像的右下角,并且恰好不超出图像范围,进行了每个字符大小的获取:
height = []
width = []
for eveStr in watermarkStr:
thisWidth, thisHeight = drawImage.textsize(eveStr, font)
height.append(thisHeight)
width.append(thisWidth)
通过这样处理之后,得到的height
列表就是所有即将水印文字的高度,width
列表是所有即将水印文字的宽度。此处要将水印放在右下角只需要在图片整体高度上减去height
列表最大值,图片整体宽度基础上减去width
列表的总和即可:
def watermarImage(image, watermarkStr):
txtImage = Image.new('RGBA', image.size, (0, 0, 0, 0))
font = ImageFont.truetype(&#