现今的各类应用中,图片的使用越来越多,而且移动设备的各类高清屏,图片质量的要求也越来越高,在网站上图片类的使用带宽已基本达到60%,如果能减少图片的带宽占用,能更好的提升用户体验以及节约成本。
随着接入终端的种类繁多,以往一张图片所有终端使用的暴力做法已跟不上潮流,我更倾向于不同的终端选择更适合的图片(尺寸、质量甚至于更优的图片格式),Tiny主要用于对图片做压缩或尺寸调整以及格式转换,以及图片区域剪辑,更简单的方式适配更多的场景。下面是我日常是遇到比较多的场景:
图片自适应等比缩放
超长宣传banner,高度固定从中间截取图片展示
针对不同的终端使用不同的图片格式、图片质量
以往为了适应这些场景,基本都是生成了几种尺寸的图片,终端在使用时根据需要选择,此种方式需要预生成图片,也很难覆盖所有终端。大部分场景都是图片达不到要求或者使用了较大分辨率的图片浪费带宽。而我更希望的是:
在终端中实时根据显示区域,自定义图片的尺寸
根据当前网络接入类型,选择不同的图片质量
根据各终端对图片格式的支持,选择更优的图片格式(如webp)
图片的各参数可以随意调整,实时生成,性能也不能太差
为了能更好适应上述的场景,希望得到的就是一个能自定义高度、宽度、图片质量、图片格式以及可以自定义剪辑图片区域的工具,实时生成但不可性能太差的图片服务。
tiny是使用golang编写的数据压缩与图片转换工具,提供HTTP与GRPC的调用方式。对于文本内容,支持gzip与br两种压缩格式。对于图片,支持png, jpeg(guetzli)以及webp三种格式转换。一般不建议使用HTTP的服务,HTTP服务仅用于平时测试使用,GRPC的性能更好一些。
HTTP
GRPC
gzip
br
png
jpeg(guetzli)
webp
对于gzip与br两种文本压缩,我主要用于网站静态文件的打包,对于静态文件生成.js.gzip以及.js.br两份文件,在nginx中根据Accept- Encoding来添加后缀指定使用相应的压缩格式。过程虽然有点绕,不过只要配置好构建脚本,后续的所有工作也都不需要再做额度的工作,总体来说也不算太麻烦(也可以把nginx中的br的压缩模块编译进去,直接使用)。
Accept- Encoding
相对于文本压缩,图片的选择就更多了,不同的格式,不同的尺寸,是否做区域剪辑,各类场景的组合,相比于文本的预生成,图片大部分都是需要使用实时生成的形式。在这要先提一下guetzli这种图片处理,它生成的jpeg文件更小但需要的时间很长,如果需要使用它建议还是做预处理的方式。
guetzli
jpeg
根据我自己的日常使用,在图格式与质量的选择,按以下两种情况:
有透明度的图片(如图标),优先使用webp(0),再使用png(90)
广告类等色彩鲜明的图片,对于质量要求不是太高的场景,可以优先使用webp(70)
webp的质量选择0是表示Lossless,图片质量按实际需要自己调整则可。相关代码在tiny,png的处理直接使用了pngquant,而guetzli则是guetzli。
tiny提供的图片转换服务只是针对开发者,完全是无法满足现实中的需要,必须的搭配它的好伙伴tiny-site才是咖啡与伴侣,它主要提三个功能:
tiny-site
用户在上传原图之后,选择分类(或自定义一个新类别),选择上传图片类型。缓存时间为HTTP头的Cache-Control: max- age,图片都是可长期缓存的,建议配置一年,在配置完成之后,点击保存则将图片保存至数据库,可在列表中查找自己上传的图片。
在上传图片之后,可以在图片列表中选择所上传的图片,有三个功能可选择:
图片预览,查看上传的图片
图片剪辑,按一半宽度、一半高度居中截取图片,生成图片地址并复制至粘贴板
图片预览,按质量选择为90,生成图片地址并复制至粘贴板
下面看看复制的两组图片地址:
/center/01CQPFKV5WYG8VD4QTVN5PYYJW-90-480-300.jpeg
/v1/01CQPFKV5WYG8VD4QTVN5PYYJW-90-0-0.jpeg
其中center表示居中剪切,总共支持三种:center, lt, tc,其中lt表示从左上角开始剪辑,tc表示中顶部中间开始剪辑。而后面文件名部分则由如下参数组合,文件ID-图片质量-图片宽度- 图片高度.图片类型,参数如下:
center
lt
tc
文件ID-图片质量-图片宽度- 图片高度.图片类型
文件ID,是在上传图片时生成的唯一ID
图片质量,根据需要选择合适的值,需要注意的是,对于webp,设置0为无损,一般用于图标
图片宽度,根据需求选择合适的宽度,0为原始宽度
图片高度,根据需求选择合适的高度,0为原始高度
图片类型,根据终端支持的图片格式选择,可选为webp,png,jpeg
在我实际使用过程中,图片质量一般是根据终端的当前网络类型选择,非wifi一般使用60,wifi环境下则是80-90。宽度与高度则根据显示区域匹配,尽可能不做1px的拉伸缩小处理。图片类型就根据终端支持的图片格式选择则好,建议优先选择webp。
在实际使用中,有部分文件上传是程序自动处理,如果这部分还需要登录认证则比较麻烦,因此需要一个基于token校验的内部接口:
curl -XPOST -d '{ "token": "内部token,不可泄露", "category": "此文件的分类", "fileType": "文件类型", "maxAge": "文件max-age", "data": "base64后的图片数据" }' 'http://tiny.aslant.site/api/files/v1/token'
经过调整后,CDN中图片类的流量减少了20%左右,虽然CDN的文件存储增长了10倍(因为不同分辨率,支持不同格式的终端不一),总体来说还是费用减少了好多,性能也有所提升。 我自建了一个测试环境,大家可以随便试用,如果有疑问可以直接在github上提问,感恩不言谢~ 测试地址:http://tiny.aslant.site/#/