java原生对于图片的编辑处理并没有特别友好,而且问题也有不少,那么作为一个java后端,如果要提供图片的编辑服务可以怎么办?也得想办法去支持业务需求,本片博文基于此进行展开
I. 调研
首先最容易想到的就是目前是不是已经有了相关的开源库,直接用不就很high了嘛,git上搜一下
1. thumbnailator
差不多四年都没有更新了,基于awt进行图片的编辑处理,目前提供了基本的图片编辑接口,开始用了一段时间,有几个绕不够去的坑,所以最后放弃了
使用姿势:
一个使用case:
问题说明:
- jpg图片编辑后,输出图片变红的问题(详情参考:兼容ImageIO读取jpeg图片变红 https://liuyueyi.github.io/hexblog/2018/01/22/%E5%85%BC%E5%AE%B9ImageIO%E8%AF%BB%E5%8F%96jpeg%E5%9B%BE%E7%89%87%E5%8F%98%E7%BA%A2/)
- 图片精度丢失(对于精度要求较高的场景下,直接使用Jdk的BufferedImage会丢失精度)
上面两个问题中,第二个精度丢失在某些对图片质量有要求的场景下比较严重,如果业务场景没那么将就的话,用这个库还是可以减少很多事情的,下面基于ImageMagic的接口设计,很大程度上参考了该工程的使用规范,因为使用起来(+阅读)确实特别顺畅
2. simpleimage
阿里的开源库,文档极其欠缺,而且良久没有人维护,没有实际使用过,感觉属于玩票的性质(个人猜测是KPI为导向下的产物)
如果想造轮子的话,参考它的源码,某些图片的处理方案还是不错的
3. imagemagic + im4java
ImageMagic/GraphicMagic 是c++的图象处理软件,很多服务基于此来搭建图片处理服务的
- 优点:稳定、性能高、支持接口多、开箱即用、靠谱
- 缺点:得提前配置环境,基本上改造不动,内部有问题也没辙
这个方法也是下面的主要讲述重点,放弃Thumbnailator选择imagemagic的原因如下:
- 支持更多的服务功能(比Thumbnailator多很多的接口)
- 没有精度丢失问题
- 没有图片失真问题(颜色变化,alpha值变化问题)
II. 环境准备
首先得安装ImageMagic环境,有不少的第三方依赖,下面提供linux和mac的安装过程
1. linux安装过程
安装完毕之后,进行测试
2. mac安装过程
依赖安装
源码安装方式与上面一致
3. 问题及修复
如果安装完毕之后,可能会出现下面的问题
提示找不到png依赖:
- 安装:一直找不到 png的依赖,查阅需要安装 http://pkgconfig.freedesktop.org/releases/pkg-config-0.28.tar.gz
执行 convert 提示linux shared libraries 不包含某个库
- 临时方案:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
- 永久方案:
4. 常见Convert命令
imagemagic的场景使用命令如下
裁图
- convert test.jpg -crop 640x960+0+0 output.jpg
旋转
- convert test.jpg -rotate 90 output.jpg
缩放
- convert test.jpg -resize 200x200 output.jpg
强制宽高缩放
- convert test.jpg -resize 200x200! output.jpg
缩略图
- convert -thumbnail 200x300 test.jpg thumb.jpg
上下翻转:
- convert -flip foo.png bar.png
左右翻转:
- convert -flop foo.png bar.png
水印:
- composite -gravity northwest -dissolve 100 -geometry +0+0 water.png temp.jpg out.jpg
添加边框 :
- convert -border 6x6 -bordercolor "#ffffff" test.jpg bord.jpg
去除边框 :
- convert -thumbnail 200x300 test.jpg thumb.jpg
III. 接口设计与实现
java调用ImageMagic的方式有两种,一个是基于命令行的,一种是基于JNI的,我们选则im4java来操作imagemagic的接口(基于命令行的操作)
目标:
对外的使用姿势尽可能如 Thumbnailtor
,采用builder模式来设置参数,支持多种输入输出
1. im4java使用姿势
几个简单的case,演示下如何使用im4java实现图片的操作
2. 使用姿势
在具体的设计接口之前,不妨先看一下最终的使用姿势,然后逆向的再看是如何设计的
上面这个方法,演示了图片的多个操作,首先是加个红色边框,然后翻转,然后旋转180°,再裁剪输出图片
所以这个封装,肯定是使用了Builder模式了,接下来看下配置参数
3. 接口设计
首先确定目前支持的几个方法:OperateType
其次就是相关的配置参数: Operate<T>
4. Builder实现
简化使用成本,因此针对图片裁剪、旋转等接口,封装了更友好的接口方式
参数的设置相关的比较清晰,唯一需要注意的是输出asFile()
,这个里面实现了一些有意思的东西
- 保存原图片(将网络/二进制的原图,保存到本地)
- 生成临时输出文件
- 命令执行
上面前两个,主要是借助辅助工具 FileWriteUtil实现,与主题的关联不大,但是内部东西还是很有意思的,推荐查看:
- https://github.com/liuyueyi/quick-media/blob/master/plugins/base-plugin/src/main/java/com/github/hui/quick/plugin/base/FileWriteUtil.java
命令执行的封装如下(就是解析Operate参数,翻译成对应的IMOperation)
5. 接口封装
包装一个对外使用的方式
IV. 测试
上面基本上完成了整个接口的设计与实现,接下来就是接口测试了
给出几个使用姿势演示,更多可以查看:https://github.com/liuyueyi/quick-media/blob/master/plugins/imagic-plugin/src/test/java/com/github/hui/quick/plugin/test/ImgWrapperTest.java
V. 其他
项目:
GitHub:
- 项目:Quick-Media https://github.com/liuyueyi/quick-media
- 源码:imagic-plugin https://github.com/liuyueyi/quick-media/tree/master/plugins/imagic-plugin
Gitee:
- 项目:Quick-Media https://gitee.com/liuyueyi/quick-media
- 源码:imagic-plugin https://gitee.com/liuyueyi/quick-media/tree/master/plugins/imagic-plugin
个人博客: 一灰灰Blog https://liuyueyi.github.io/hexblog
基于hexo + github pages搭建的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
声明
尽信书则不如,已上内容,纯属一家之言,因本人能力一般,见识有限,如发现bug或者有更好的建议,随时欢迎批评指正
- 微博地址: 小灰灰Blog