Java5分钟制作海报
创始人
2024-03-28 16:45:16
0

一、需求背景

我们经常在多终端应用开发中会遇到这样的需求:用户在浏览商品时觉得不错,希望分享给朋友。此时终端(安卓、苹果、H5等)生成一张精美的商品海报,通过微信或者其他途径分享给他人。也可能会遇到需求:制作个人名片打印出来或者分享给他人。效果大概是这样的:556606965a87b3e6ced4624e8461bf8a.png也可能是这样b80c39c49a445284a23736e89a184918.png368e82d7a59490774c11df5fea3b03bb.png(上面的图都是我从网上临时找的,只做参考学习,避免广告已经做了部分处理。) 刚开始设计这个需求的时候,我们是在前端来完成的,即由安卓、IOS、H5、微信几个端的开发者自主实现功能。各端完成开发后发布到全网,很快就发现一些用户机型上出现了兼容性的问题(C端安卓机型有很多版本)。用户手机安卓版本从5.N到最新的版本、从ip6到最新款,最大跨度超10年,这种兼容性问题对我们来说无法预料。曾尝试使用的dom-to-image和html2canvas效果都不太理想,解决了白屏、跨域问题又遇到低版本不支持标签的问题…。一通折腾,最后我们决定在服务端将海报图片生成好,在终端直接显示图片。

二、用JAVA生成海报

从上面的三张海报,我选《美女》图,作为今天演示效果。(在做此演示时并没有使用之前项目上的图,我也是首次照着图在开发)。首先将海报分别为3类,背景图、其他图、文字、二维码。如:1-底图纯白,2-商品介绍图,3-头像 素材,4-“严选”字样的图素材,5-带色的二维码,6-标题、价格等文字,实际开发中根据视觉和美工给的图即可。先上我完成的最终效果:d590dcb8d3fb5984963cb3ba5f416a9d.png简单做一下,大概和视觉图差不多了, 虽然有点糙但足以表达到效果。

2.1 Easy Poster 易海报生成器

在开发海报过程中,我也找了不少资料,花费了较多时间,后来发现了Easy Poster的设计还是不错的。所以在开发结束以后,我对代码进行了重新整理完善:修复了一些问题,并增加了二维码功能,成为开箱即用的海报生成工具。接下来,我将介绍一下如何用来快速的制作海报。创建一个新的海报,只需要3步即可完成 修改pom.xml添加依赖和打包过滤字体库。创建海报对象及配置相关属性。传入参数,生成海报

2.2修改pom.xml添加依赖和打包过滤字体库。

pom.xml

881.16.185.7.193.4.16.8.81.7.13

org.projectlomboklombok${lombok.version}compileorg.slf4jslf4j-api${slf4j.version}com.google.zxingcore${zxing.version}cn.hutoolhutool-all${hutool-all.version}org.testngtestng${testng.version}test


org.apache.maven.pluginsmaven-resources-pluginttfwoffwoff2

*注意:我们海报用到了字体作为资源文件引入,在经过maven的filter,会破坏font文件的二进制文件格式 导致打包异常,此处要一定要注意。

2.3 创建海报对象及配置相关属性

CommodityPosterPojo.java

package com.naiqing.poster.demo;import com.quaint.poster.annotation.PosterBackground;
import com.quaint.poster.annotation.PosterBarCodeCss;
import com.quaint.poster.annotation.PosterFontCss;
import com.quaint.poster.annotation.PosterImageCss;
import com.quaint.poster.core.abst.AbstractDefaultPoster;
import com.quaint.poster.core.dto.PosterBarcode;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Tolerate;import java.awt.*;
import java.awt.image.BufferedImage;/*** 〈商品分享海报元素及相关参数定义〉
** @author naiqing* @Date 2022/1/21* @see [相关类/方法]* @since [产品/模块版本]*/ @EqualsAndHashCode(callSuper = true) @Data @Builder public class CommodityPoster2Pojo extends AbstractDefaultPoster {/*** 背景图*/@PosterBackground(width = 540, height = 868)private BufferedImage backgroundImage;/*** 商品图*/@PosterImageCss(position = {0, 0}, width = 540, height = 614)private BufferedImage commodityImage;/*** 严选图标*/@PosterImageCss(position = {16, 625}, width = 50, height = 28)private BufferedImage yanxuanImage;/*** 商品标题*/@PosterFontCss(position = {16, 625}, size = 22, canNewLine = {1, 482, 2}, style = Font.BOLD)private String commodityTitle;/*** 特权价*/@PosterFontCss(position = {16, 706}, size = 20, color = {247,23,61})private String vipPrice;/*** 原价*/@PosterFontCss(position = {16, 742}, size = 15, color = {51, 51, 51}, delLine = true)private String oldPrice;/*** 头像*/@PosterImageCss(position = {10, 780}, width = 55, height = 55, circle = true)private BufferedImage headImage;/*** 昵称*/@PosterFontCss(position = {77, 788}, color = {85,85,85}, name = "腾祥爱情体细简", style = Font.BOLD)private String nickName;/*** 昵称下的描述*/@PosterFontCss(position = {75, 813}, size = 15, color = {104,104,104}, name = "腾祥爱情体细简")private String nickDesc;/*** 二维码*/@PosterBarCodeCss(position = {376, 695}, width = 130, height = 130, foreColor = {17,125,124})private PosterBarcode qrCode;/*** 二维码字*/@PosterFontCss(position = {386, 833}, size = 20, color = {104,104,104}, center = true)private String qrCodeText;@Toleratepublic CommodityPoster2Pojo() {} }

此处定义了海报全部的元素,通过注解:背景图片@PosterBackground、其他图片@PosterImageCss、字体 @PosterFontCss和二维码@PosterBarCodeCss,来配置位置、宽度等参数(更多参数可通过源码了解)。

@PosterBarCodeCss 二维码注解,只适用类PosterBarcodeDto
@PosterBackground 背景图片注解、@PosterImageCss,只适用类BufferedImage
@PosterFontCss文字注解,只适用类String

2.4如何快速得到x\y坐标和width\heigth尺寸

正常来说,视觉稿给到我们开发的时候,页面上都是可以快速得到每个元素的位置和尺寸,但此处因为是从网上找到整图,所以只能自己动手了。此处我是通过ps打开图片,打开”窗口-信息“,可以查看到鼠标的坐标及圈选的尺寸,如下图可以快速得到各元素的位置:a1df31d5c7fe92b29d37ec2386b8f35e.png

2.5 传入参数,生成海报

1) 加载字体库 在此调用生成海报之前,我们要将用到的字体库放到项目中,比如说我这里用到了2个字体库:resources\fonts\simkai.ttf和resources\fonts\TTAiQingXiJ_0.ttf。这里我要特别说明:如果不加载字体库在windows下也是可以直接使用的(会默认使用宋体),但是在将服务发布到服务器下Linux时所有中文都会乱码,因为Linux下并没有相应字体库。2)生成海报 我用一个单元测试来实现海报生成调用示范,传入商品名称相关信息

package com.naiqing.poster.demo;import com.quaint.poster.core.dto.PosterBarcode;
import com.quaint.poster.core.impl.PosterBarcodeImpl;
import lombok.SneakyThrows;
import org.testng.annotations.Test;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;/*** 〈测试海报〉
** @author naiqing* @Date 2022/1/22* @see [相关类/方法]* @since [产品/模块版本]*/ public class CommodityPoster2Test {@SneakyThrows@Testpublic void testCreate() {//背景图,此处测试我是用的本地图,实际开发可换成网络获取图片(下面有示例)BufferedImage backgroundImage = ImageIO.read(new File("D:\\temp\\s_bg.jpg"));//商品主图BufferedImage commodityImage = ImageIO.read(new File("D:\\temp\\s_commodity.jpg"));//严选图标BufferedImage yanxuanImage = ImageIO.read(new File("D:\\temp\\s_yanxuan.jpg"));//头像BufferedImage headImage = ImageIO.read(new File("D:\\temp\\s_head.jpg"));//二维码logoBufferedImage qrLogo = headImage;//二维码内容String qrContent = "http://www.baidu.com";//全局默认字体(如果不将字体库资源引入,在windows下没问题,但linux没有默认的"宋体"会显示乱码)InputStream in1 = this.getClass().getResourceAsStream("/fonts/simkai.ttf");Font defaultFont = Font.createFont(Font.TRUETYPE_FONT, in1);//昵称显示的字体(此字体库是从网上下载的,非windows自带),使用时引用FontName字体名称即可(字体名称:双击字体库可以看到字体名称)InputStream in2 = this.getClass().getResourceAsStream("/fonts/TTAiQingXiJ_0.ttf");Font txin2 = Font.createFont(Font.TRUETYPE_FONT, in2);CommodityPoster2Pojo shareCommodityInfo = CommodityPoster2Pojo.builder().backgroundImage(backgroundImage).commodityImage(commodityImage).yanxuanImage(yanxuanImage).commodityTitle(" 雾中女孩2022冬季新款女装连帽拉链长袖棉服 WH88888").vipPrice("特权价¥0.01").oldPrice("售价¥268").headImage(headImage).nickName("叫我胡歌啊").nickDesc("邀请好友享受内部优惠价").qrCode(PosterBarcode.builder().content(qrContent).logo(qrLogo).build()).qrCodeText("微信扫一扫").build();//创建海报生成器PosterBarcodeImpl poster = new PosterBarcodeImpl<>();//设置默认字体库 /安装用到的全部字体库(支持传多个)poster.defaultFont(defaultFont).installFonts(txin2,...);//生成海报BufferedImage image = poster.annotationDrawPoster(shareCommodityInfo).draw(null);ImageIO.write(image, "png", new File("D:\\temp\\out2.png"));} }

可以看到用起来还是非常简单的,开箱即用!有了这个工具,5分钟可以搞一个海报出来!再也不需要去考虑APP端的不确定的兼容问题了,也不用兴师动众让安卓、苹果、H5等多端的开发者多人开发了。美滋滋~ 我上面的示例是使用的本地图,也可以使用图片链接。

//远程图片BufferedImage backgroundImage = ImageIO.read(new URL("https://img-blog.csdnimg.cn/8bf7094ae7b044f495035c8ea734dca8.png"));

如何使用自定义字体库?当我们在制作海报时,视觉给的效果图可能除了颜色、粗体要求以外,可能还会要求使用指定的字体。此时我们要拿到此字体库文件”*.ttf“并放到项目资源目录下,比如我的是resources\fonts\*.ttf。第二步,是我们要得到此字体库的字体名称,在创建海报时配置@PosterFontCss 设置字体需要指定字体名称。双击此字体库文件,第一行就能看到字体名称,如下图:如何将海报图片转成base64返回给前端

//将生成的海报图片以base64形式回写至终端
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(image, "png", stream);
String asBase64 = "data:image/png;base64,"+Base64.encode(stream.toByteArray());
System.out.println(asBase64);

三、 用到的技术及相关源码

3.1 Easy Poster 易海报生成器

以上的源码和示例代码均在gitee上,可直接下载。欢迎大家一起来修复完善此工具。https://gitee.com/naiqing/easyposter 在此特别感谢框架Easy Poster 的作者,我是基于此框架,修复了一些问题后进行的二次开发。

3.3 二维码生成zxing

对于二维码的生成我是使用了谷歌的zxing,然后利用hutool-all来简化调用。

39f1fcb01da33dc290e6567c9c6a4feb.jpeg

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...
有效的括号 一、题目 给定一个只包括 '(',')','{','}'...
【Ctfer训练计划】——(三... 作者名:Demo不是emo  主页面链接:主页传送门 创作初心ÿ...