pil获得图片_「实践」如何优雅地给网站图片加水印

news/2024/5/9 11:31:49/文章来源:https://blog.csdn.net/weixin_33023513/article/details/112191879
很多论坛、博客在进行图片上传之后,都会给自己的图像加上水印,这样可以证明这张图片「属于我」或者是「来自我的博客/网站」。那么使用 Serverless 技术来加水印的方法比传统方法好在哪儿呢,本文将对此进行一个简单的分享。

传统的加水印的方法,通常是在流程内进行。即:

d3ce87f8e74e8a7ec165bff6402d55fc.png

这种做法虽然可行,但是无疑会增加单次请求,服务端的压力,如果是高并发的情况下,或者多人上传多张大图的时候,那么可能就会造成自身服务器资源效果过大。

如果在加水印过程中失败,就有可能导致图像存储失败,致使数据丢失,并不理智。所以后来有人做了如下改进:

9c0c7942c0298c70b9cd59f9f5199490.png

这样做法的好处就是 —— 我们可以快速将图片存储,存储之后通过一个单独处理的线程,对任务列表进行处理,这样一方面是可以保证我们马上把用户上传的图片存储,并且可以显示,同时也可以在后台进行水印处理,待处理之后,再将图片覆盖或者单独存储,用户如果需要读取图片时,可以自动变为已经水印后的图片。

这种做法相对于前者来说可能稍微复杂一些,但是实际上却是在数据上更加稳定,服务端压力更小,更加可控的一种操作。但是,这整个流程还是要在自己的服务器上做完,现在已经有很多人将图片等资源存储到腾讯云的对象存储(COS)中,那么可不可以通过某些 COS 触发器与云函数 SCF 结合,实现一个不在自己服务器加水印的流程呢?

本文将以腾讯云函数 SCF 的函数模板(Python 语言)为例,进行一个简单的分享。

实验

新建函数

在无服务器云函数中,选择模板函数:

24ee60bad70bb2e9a9b8fdf8c733320d.png

通过搜索「图像」关键词,选中图像压缩,并且确定建立。保存之后,点击函数代码,进行代码编写。

d0c9975e3f8fc24b7f1000728b854e2a.png

COS 触发器

有些人可能对 COS 触发器还不是很了解,此时可以点击配置,来熟悉 COS 触发器样式:

452e8f99d8e8f3b1f7b190f7a11e7fcb.png

可以看到如下:

{"Records":[{"event": {"eventVersion":"1.0","eventSource":"qcs::cos","eventName":"cos: ObjectCreated: *","eventTime":1501054710,"eventQueue":"qcs:0:cos:gz:1251111111:cos","requestParameters":{"requestSourceIP": "111.111.111.111","requestHeaders":{"Authorization": "上传的鉴权信息"}}},"cos":{"cosSchemaVersion":"1.0","cosNotificationId":"设置的或返回的 ID","cosBucket":{"name":"bucketname","appid":"appId","region":"gz"},"cosObject":{"key":"/appid/bucketname/DSC_0002.JPG","size":2598526,"meta":{"Content-Type": "text/plain","x-cos-meta-test": "自定义的 meta","x-image-test": "自定义的 meta"},"url": "访问文件的源站url"}}}]
}

这里面可以看到整个一个数据结构,需要注意 Records 是一个数组格式,其次就是:

"cosBucket":{"name":"bucketname","appid":"appId","region":"gz"}

这里面是由该 bucket 触发

"cosObject":{"key":"/appid/bucketname/DSC_0002.JPG","size":2598526,"meta":{"Content-Type":"text/plain","x-cos-meta-test":"自定义的 meta","x-image-test":"自定义的 meta"},"url":"访问文件的源站 url"}

这里面的 key 是在上述 bucket 中新建的文件名字。

所以,我们可以按照我们的实际情况,将上面的内容简单修改一下,成为我们格式,以便测试(在生产中,这个是自动生成的触发格式,并不需要我们修改,我们修改只是为了测试)

{"Records":[{"event": {"eventVersion":"1.0","eventSource":"qcs::cos","eventName":"cos: ObjectCreated: *","eventTime":1501054710,"eventQueue":"qcs:0:cos:gz:1251111111:cos","requestParameters":{"requestSourceIP": "111.111.111.111","requestHeaders":{"Authorization": "上传的鉴权信息"}}},"cos":{"cosSchemaVersion":"1.0","cosNotificationId":"设置的或返回的 ID","cosBucket":{"name":"mytestcos","appid":"appId","region":"gz"},"cosObject":{"key":"test.png","size":2598526,"meta":{"Content-Type": "text/plain","x-cos-meta-test": "自定义的 meta","x-image-test": "自定义的 meta"},"url": "访问文件的源站url"}}}]
}

这里主要修改了我的 cosBucket-name:mytestcos,以及 key:test.png

971eeb5d498572a244b9a9cbf6717a73.png

代码修改

之所以使用现有的模板,是因为该模板的有 PIL 和 qcloud_cos_v5 等相关 package,而这两个 package 正是我们即将需要的,这样就可以省去我们打包函数的流程,只需要进行简单修改即可实现。

添加水印:

def add_word(pic_path, save_path):# 打开图片im = Image.open(pic_path).convert('RGBA')# 新建一个空白图片,尺寸与打开图片一样txt = Image.new('RGBA', im.size, (0, 0, 0, 0))# 设置字体fnt = ImageFont.truetype("/tmp/font.ttf", 40)# 操作新建的空白图片>>将新建的图片添入画板d = ImageDraw.Draw(txt)# 在新建的图片上添加字体d.text((txt.size[0] - 220, txt.size[1] - 80), "By Dfounder", font=fnt,  fill=(255, 255, 255, 255))# 合并两个图片out = Image.alpha_composite(im, txt)# 保存图像out.save(save_path)

在添加水印的时候,我们设置的是文字水印,所以需要设置字体和字号:

fnt = ImageFont.truetype("/tmp/font.ttf",40)

此时,我们需要在执行之前,先将字体文件传入到 /tmp/ 文件夹下:

response = client.get_object(Bucket="mytestcos-12567****", Key="font.ttf", )
response['Body'].get_stream_to_file('/tmp/font.ttf')

以我的 cos 为例:

dae85cb9e002991f60474b5048cccfed.png

然后,接下来就是对触发的 event 进行解析,包括获得新建的图像名称,从 COS 拉取,放到本地,然后进行水印等,再上传回新的 COS 中:

for record in event['Records']:try:bucket = record['cos']['cosBucket']['name'] + '-' + str(appid)key = record['cos']['cosObject']['key']key = key.replace('/' + str(appid) + '/' + record['cos']['cosBucket']['name'] + '/', '', 1)download_path = '/tmp/{}'.format(key)upload_path = '/tmp/new_pic-{}'.format(key)# 下载图片try:response = client.get_object(Bucket=bucket, Key=key, )response['Body'].get_stream_to_file(download_path)except CosServiceError as e:print(e.get_error_code())print(e.get_error_msg())print(e.get_resource_location())# 图像增加水印add_word(download_path, upload_path)# 图像上传response = client.put_object_from_local_file(Bucket=to_bucket,LocalFilePath=upload_path.decode('utf-8'),Key=("upload-" + key).decode('utf-8'))except Exception as e:print(e)

此处说明一下,为什么要有两个存储桶?

因为我们要把一个存储桶作为触发 SCF 函数的「工具」,如果我们将水印结果再次写回这个存储桶,在不进行额外判断和处理的前提下,那么这个水印后的图片会再次水印,反反复复造成恶劣的循环,所以此处建立两个存储桶,可以降低难度,也可以保护性能,减少 BUG 诞生。

完整代码如下:

# -*- coding: utf-8 -*-from PIL import Image, ImageFont, ImageDraw
from qcloud_cos_v5 import CosConfig
from qcloud_cos_v5 import CosS3Client
from qcloud_cos_v5 import CosServiceError
from qcloud_cos_v5 import CosClientErrorappid = **  # 请替换为您的 APPID
secret_id = ***'  # 请替换为您的 SecretId
secret_key = **'  # 请替换为您的 SecretKey
region = u'ap-chengdu'  # 请替换为您bucket 所在的地域
token = ''
to_bucket = 'tobucket-12567***'  # 请替换为您用于存放压缩后图片的bucketconfig = CosConfig(Secret_id=secret_id, Secret_key=secret_key, Region=region, Token=token)
client = CosS3Client(config)response = client.get_object(Bucket="mytestcos-12567***", Key="font.ttf", )
response['Body'].get_stream_to_file('/tmp/font.ttf')def add_word(pic_path, save_path):# 打开图片im = Image.open(pic_path).convert('RGBA')# 新建一个空白图片,尺寸与打开图片一样txt = Image.new('RGBA', im.size, (0, 0, 0, 0))# 设置字体fnt = ImageFont.truetype("/tmp/font.ttf", 40)# 操作新建的空白图片>>将新建的图片添入画板d = ImageDraw.Draw(txt)# 在新建的图片上添加字体d.text((txt.size[0] - 220, txt.size[1] - 80), "By Dfounder", font=fnt,  fill=(255, 255, 255, 255))# 合并两个图片out = Image.alpha_composite(im, txt)# 保存图像out.save(save_path)def main_handler(event, context):for record in event['Records']:try:bucket = record['cos']['cosBucket']['name'] + '-' + str(appid)key = record['cos']['cosObject']['key']key = key.replace('/' + str(appid) + '/' + record['cos']['cosBucket']['name'] + '/', '', 1)download_path = '/tmp/{}'.format(key)upload_path = '/tmp/new_pic-{}'.format(key)# 下载图片try:response = client.get_object(Bucket=bucket, Key=key, )response['Body'].get_stream_to_file(download_path)except CosServiceError as e:print(e.get_error_code())print(e.get_error_msg())print(e.get_resource_location())# 图像增加水印add_word(download_path, upload_path)# 图像上传response = client.put_object_from_local_file(Bucket=to_bucket,LocalFilePath=upload_path.decode('utf-8'),Key=("upload-" + key).decode('utf-8'))except Exception as e:print(e)

这里面需要注意这几个参数:appid、secret_id、secret_key、to_bucket

这几个参数的来源如下:

e45827dc68051721d5d599aa7706b37f.png

而 secretid,secretkey 则需要在这里获取:

6607bbf1eb6cc26587b9fb3272bbc16b.png

测试

之前我已经上传了一个测试图片在这个 bucket 中,名字是:test.png

f038bbc4d3ee79325474ca73253dda1b.png

图片是这样子:

3118a2c10cd232c04f855f48c91398bb.png

然后我们进行一下测试:

b38b1a57a1a0d9e8925557688eb6296c.png

可以看到,已经测试成功,接下来我们可以去我们的目标 bucket 中看看:

3cd0199675adb9b3b58508f50861172a.png

可以看到成功生成了一个图片:

7d5058a4f7951d2f8dbaf7f5e5d1a1e6.png

可以看到图片的右下角,有我们代码中添加的水印:

641450aef9a110b5da268ac629e7f2cf.png

至此,我们完成了通过云函数 SCF 为您的网站图片添加水印的基本流程。

额外想说的

其实,这篇文章也算是抛砖引玉,大家不仅可以通过这个流程压缩图像、添加水印,甚至还可以对图像进行其他操作。例如图像风格化处理等一些深加工,而这一切过程,都不会占用自身服务器资源,而是通过云函数 SCF 来完成的。

即使面对高并发,有大量的图片上传时,我们要做的也仅仅是通过 SDK,将图片传入到 COS 中。


作者介绍:腾讯云高级研发工程师刘宇
推荐阅读:
Serverless 基本概念入门​zhuanlan.zhihu.com
d84f624e23fdad41208ea97be9f0bcea.png
Serverless 的运行原理与组件架构​zhuanlan.zhihu.com
373d226f5416f9ff5e7e8afcb77e5e00.png
Serverless 的开发者工具建设​zhuanlan.zhihu.com
8ae146709ab529467442c8df1feaf8dc.png
GitHub:
TencentCloud/serverless​github.com
5a72f41353681316f5520d44d736ea05.png

欢迎关注:腾讯云 Serverless 团队

我们专注于 Serverless 架构的最佳实践!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_788205.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

某高校校园卡网站模拟登陆(php)

让我们先来看登陆界面,这里可以使用卡号或学号,这里我们使用卡号,其实是一样的输入卡号后,点击密码输入框,弹出一个密码键盘输入密码以后,点击验证码框出现验证码输入验证码以后正常登陆下面来看看这个登陆…

关于动态网站的简单爬虫实现

1.XPath的使用 用来解析XML, 也可以用来解析HTML。同Beautiful Soup一样,在XPath中提供了非常简洁的节点选择的方法,Beautiful Soup主要是通过.的方式来进行子节点或者子孙节点的选择,而在XPath中则主要通过/的方式来选择节点。 …

jsp oracle 网站建设_网站建设5大基础知识,你知道吗?

原标题:网站建设5大基础知识,你知道吗?现在网站建设普及度越来越广,做网站建设的企业也越来越多,引起不少对网站建设知识学习的追求者,一时间各种建站系统遍布互联网。在做网站优化中,也许对网站…

多布局怎么搭建_怎么建设文创饰品网站?需要多少钱?

近几年文创周边产品很受欢迎,因此也诞生了不少文化艺术、文创饰品类企业。文创产品要想顺利销售出去,就需要广拓渠道,尤其要注重互联网窗口的建设,因此建设一个自己的官方网站自然是少不了的。「上线了」建站案例文创饰品公司要建…

python3网站攻击_Python实现DDos攻击实例详解

SYN 泛洪攻击 SYN泛洪攻击是一种比较常用的Dos方式之一。通过发送大量伪造的 TCP 连接请求,使被攻击主机资源耗尽(通常是 CPU 满负荷或内存不足)的攻击方式 我们都知道建立 TCP 连接需要三次握手。正常情况下客户端首先向服务器端发送SYN报文…

node获取图片路径_在Node.js上接入Paddle Lite,让你的网站具备AI推理能力

【飞桨开发者说】李睿,北京邮电大学学生,人工智能和移动开发爱好者。随着桌面端Electron技术逐步崛起,基于Electron开发的代码编辑器、聊天软件、游戏等层出不穷。对于习惯使用Node.js进行后端开发的朋友来说,开发一套漂亮的桌面U…

bootstrap获取下拉框数据_网站SEO优化推广关键词可以通过哪些途径获取,分析百度搜索原理...

一、百度下拉框,从百度下拉框里可以获取用户在搜索引擎搜索过的关键词,这类词符合用户的搜索习惯。二、百度相关搜索,在搜索引擎页面底部,有个百度相关搜索,这些词也可以选择,这是百度算法根据用户浏览过的…

静态网站生成器

静态网站生成器 静态网站相比动态网站具备无需依赖应用服务器,性能优越,部署简单等特点。特别适合生成静态文档,个人博客,饱受开发者的青睐。相比学会使用,掌握工作原理也尤为重要。 一个静态网站生成器的工作流程通…

SEO优化来了

搜索引擎工作原理 当我们在输入框中输入关键词,点击搜索或查询时,然后得到结果。深究其背后的故事,搜索引擎做了很多事情。 在搜索引擎网站,比如百度,在其后台有一个非常庞大的数据库,里面存储了海量的关…

织梦网站地图更新自由列表html,织梦自由列表更新使用教程

当我们用织梦网站建立了一个自由列表后就相当于建立了一个类似其它栏目的一个列表,跟其它栏目建立了一个最终列表页一样,当建立完自由列表后,也需要生成列表html,也就是自由列表的更新,如下图所示:(此图片来…

大型网站架构演变和知识体系(转)

之前也有一些介绍大型网站架构演变的文章,例如LiveJournal的、ebay的,都是非常值得参考的,不过感觉他们讲的更多的是每次演变的结果,而没有很详细的讲为什么需要做这样的演变,再加上近来感觉有不少同学都很难明白为什么…

http 升级 https 影响原来的链接吗_http切换https的SEO完美解决办法

对于网站http协议切换为https协议,这不仅仅能够提升网站的安全度,还可以提升网站在搜索引擎的权重。因为像百度针对https协议的站点有明确的提权政策。百度认为更加安全的站点应该获得更优质的展现,进而给予优先展示。那么针对SEO的工作而言&…

nofollow标签_网站被加上nofollow对SEO有什么危害?网站nofollow标签知多少?

关于以上问题我总结了一下网上比较优秀的关于nofollow的文章,希望能对新手有所帮助nofollow标签的介绍nofollow是一个HTML标签的属性值,nofollow 是一个HTML标签的属性值。它的出现为网站管理员提供了一种方式,即告诉搜索引擎“不要追踪此网页…

php源码仿三一重工,仿三一重工大气企业网站php源码

大小:21.55M编码:GBK简体类别:机械电子★模板介绍★源码名称:仿三一重工大气企业网站php源码仿三一重工大气企业网站php源码,测试完整无错,兼容主流浏览器。模板包含安装说明,并包含测试数据。本…

如何查询一个网站的服务器大小写,网站页面的大小写

网站页面的大小写 内容精选换一换云速建站不支持自适应宽度,推荐使用网站宽度为1200px,设置方法请参考网站基础设置。将空白处下方的模块或页脚整体上移,遮盖住空白处,然后保存修改。云速建站没有固定长度,网页的长度取…

在内网打造可以从外网访问的网站和服务

最近在内网建了一个简单的网站,利用路由器,使网站可以从外网访问。 首先利用appserv套件搭建一个phpmysqlapchephpmyadmin环境,安装十分简单,直接下一步就行了,中途可能要填写网络端口和Mysql数据库密码,网…

iis运行html提示500错误,IIS发布网站出现Http—500错误

IIS服务器可以作为一个Web服务器单独使用,也可以与相兼容的工具一起使用,它可以用来建立Internet商务、访问和操作来自不同数据源的数据以及创建Web应用程序,其中这些应用程序利用服务器脚本和组件代码来完成一些客户-服务器功能。客户端访问…

一键seo提交收录_Api提交百度搜索进行文章收录-网站SEO

网站内容如果想被搜索引擎(百度/google)收录,除了提供robots.txt等着爬虫来爬以外,如果想最快的被百度收录可以在熊掌号平台进行注册,可以通过在平台上进行页面改造、站点同步等方式提高百度收录,但是最有效的方式是使用api主动向…

网站互点排名掉了网站互点排名掉了网站互点_影响网站关键词排名不稳定的6个因素及优化建议...

很多站长朋友消耗大量的时间成本,人力成本做网站关键词排名,并让排名达到理想状况,却发现网站关键词排名不稳定,时上时下,飘忽不定。针对这种情况,建议站长或seo优化人员针对排名不稳定的原因做具体分析&am…

做服务器_美国站群服务器做网站优化效果怎么样

我们接触过不同的服务器,普通的网站服务器,高配的游戏服务器,金融行业的抗攻击服务器,多IP服务器等等。说到多IP服务器,可能第一时间就会想到站群服务器。众所周知,在早些时候,很多企业站长都会…