使用微博、微信的用户都会发现,朋友圈中有的文章中都是直接一张长图文表述。使用长图文可以足各种宣传需求,与社交分享无缝集成,扫一扫轻松分享。那么,使用Java开发如何实现长图文生成呢?

目标
首先定义下我们预期达到的目标:根据文字 + 图片生成长图文
目标拆解
1)支持大段文字生成图片
2)支持插入图片
3)支持上下左右边距设置
4)支持字体选择
5)支持字体颜色
6)支持左对齐,居中,右对齐
预期结果
我们将通过spring-boot搭建一个生成长图文的http接口,通过传入参数来指定各种配置信息,下面是一个终调用的示意图
设计&实现
长图文的生成,采用awt进行文字绘制和图片绘制
1. 参数选项 ImgCreateOptions
根据我们的预期目标,设定配置参数,基本上会包含以下参数
2. 封装类 ImageCreateWrapper
封装配置参数的设置,绘制文本,绘制图片的操作方式,输出样式等接口
3. 内容填充 GraphicUtil
具体的内容填充,区分为文本绘制和图片绘制
设计
考虑到在填充的过程中,可以自由设置字体,颜色等,所以在我们的绘制方法中,直接实现掉内容的绘制填充,即 drawXXX 方法真正的实现了内容填充,执行完之后,内容已经填充到画布上了。
图片绘制,考虑到图片本身大小和终结果的大小可能有冲突,采用下面的规则
绘制图片宽度 <=(指定生成图片宽 - 边距),全部填充
绘制图片宽度 >(指定生成图片宽 - 边距),等比例缩放绘制图片
文本绘制,换行的问题
每一行允许的文本长度有限,超过时,需要自动换行处理
文本绘制
考虑基本的文本绘制,流程如下
1、创建BufferImage对象
2、获取Graphic2d对象,操作绘制
3、设置基本配置信息
4、文本按换行进行拆分为字符串数组, 循环绘制单行内容
1)计算当行字符串,实际绘制的行数,然后进行拆分
2)依次绘制文本(需要注意y坐标的变化)
内容渲染
前面只是给出了单块内容(如一段文字,一张图片)的渲染,存在一些问题如:绘制的内容超过画布的高度如何处理?
1)文本绘制要求传入的文本没有换行符,否则换行不生效
2)交叉绘制的场景,如何重新计算y坐标
解决这些问题则是在 ImgCreateWrapper 的具体绘制中进行了实现:根据换行符对字符串进行拆分;计算绘制内容终转换为图片时,所占用的高度;重新生成画布 BufferedImage result;如果result为空,则直接生成。如果终生成的高度,超过已有画布的高度,则生成一个高的画布,并将原来的内容绘制上去。需要注意的是画布的生成规则,特别是高度超过上限之后,重新计算图片高度时,需要额外注意新增的高度,应该为基本的增量与(绘制内容高度+下边距)的较大值。
http接口
上面实现的生成图片的公共方法,在 quick-media 工程中,利用spring-boot搭建了一个web服务,提供了一个http接口,用于生成长图文,终的成果就是我们开头的那个gif图的效果。
