golang图片处理
#前言
不得不感慨,前端的发展迅速以至于我觉得在前端样式下一小段 css 的事情,服务端实现起来无比复杂,甚至无法实现。
所以其实图片编辑的操作一直以来都是由前端或者客户端完成的。但,任何客户端的用户行为其实都是不可信的,对于一个图像裁剪,如果接入审核流又会过于繁重。服务端处理在一定程度上能够解决这个问题,如果这个场景其实不会特别频繁的话。
网上看了很多关于 golang 图像处理的,太复杂,甚至有的库调用了 open-cv,如果我都调用 open-cv 了= =,感觉也没你 go 什么事情了,python 不香吗。
#简单版本
还是以炉石的卡牌做例子,最近帮营地社区做了一个卡组的整合服务,可以看到外服(玩家已同意授权的前提下)前 200 玩家的卡组信息。
数据上只有诸如AAEBAf0EEoUX0MECtPwC9KsDxbgD4MwD5dED9tYDne4DoIoE5bAEhLIE27kEqd4El+8Eo5AF/cQF0fgFC8ABywS4tgOF5AOu9wPK3gSQlgWqmAXgwwXQ+AWxngYAAQOEuwL9xAXl0QP9xAWmkwX9xAUAAA==
这样的代码,人不是机器,读不懂,所以需要解码,解码可以参考 用 golang 解析 varint。
但其实图片是最直观的,抱着学习的态度,熟悉一下 golang 的图片操作。
整个流程简单下来可以概括成这样:
- 新建一个指定大小的画布(一张卡固定大小)
- 上底色
- 拿到原始素材
- 放缩比例
- 把这张图贴到我们的画布上(现实中是先裁切,再贴图,代码层面两者可以同时完成)
#新建画布
1 | import ( |
指定整个画布的大小,通过指定左上角和右下角的点的方式。
#上底色
笑死,简单的不用上底色
#放缩
1 | import ( |
resize
是个我看网上用的还比较多的包,本质上是指定长宽的放缩,但是如果你其中一个值不写,会默认等比例放缩。
原始素材来源于一个开源的平台:https://hearthstonejson.com/,走文件下载和缓存的方案就好。
1 | var b []byte |
但是需要注意的是,图像操作基本上的结构/接口都是image.Image
,需要解码。
#贴图
是整个流程中的核心操作:
1 | import ( |
1 | func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op) { |
Draw
方法的函数定义如上,本质上是这样几个信息:
- 往哪里画
- 在最终的画布上预留给贴图的空间大小,是一个矩形框,用左上角和右下角的点表示。
- 要贴的图
- 从要贴的图的哪个点开始,往画布上贴(拷贝像素点?)
- 操作方式
1 | // Op is a Porter-Duff compositing operator. |
官方的文档其实我没太懂,而且也很复杂。但是根据我实际的操作结果来看,Over
更像是贴的操作,这个自己尝试即可。
#导出
最后转成文件:
1 | out, err := os.Create(filename) |
#复杂版本
#上底色
1 | gray := color.RGBA{R: 41, G: 46, B: 60, A: 255} |
用image.Uniform
形成一个单一颜色的矩形,贴入画布
#文字
1 | import ( |
最终下来效果其实是这样的:
令我意外的是服务端的渲染速度出奇的快,没有想象中的延时。
#参考链接
#最后
如有不正确的地方,欢迎批评指正。