Java5分钟制作海报

news2024/12/25 7:36:28

一、需求背景

我们经常在多终端应用开发中会遇到这样的需求:用户在浏览商品时觉得不错,希望分享给朋友。此时终端(安卓、苹果、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

<properties>
 <maven.compiler.source>8</maven.compiler.source>
 <maven.compiler.target>8</maven.compiler.target>
 <lombok.version>1.16.18</lombok.version>
 <hutool-all.version>5.7.19</hutool-all.version>
 <zxing.version>3.4.1</zxing.version>
 <testng.version>6.8.8</testng.version>
 <slf4j.version>1.7.13</slf4j.version>
</properties>
<dependencies>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <version>${lombok.version}</version>
 <scope>compile</scope>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>${slf4j.version}</version>
 </dependency>
 <!-- 二维码生成 -->
 <dependency>
 <groupId>com.google.zxing</groupId>
 <artifactId>core</artifactId>
 <version>${zxing.version}</version>
 </dependency>
 <dependency>
 <groupId>cn.hutool</groupId>
 <artifactId>hutool-all</artifactId>
 <version>${hutool-all.version}</version>
 </dependency>
 <dependency>
 <groupId>org.testng</groupId>
 <artifactId>testng</artifactId>
 <version>${testng.version}</version>
 <scope>test</scope>
 </dependency>
</dependencies>
<!-- SpringBoot项目的maven项目引用的字体库font经过maven的filter,会破坏font文件的二进制文件格式 -->
<build>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-resources-plugin</artifactId>
 <configuration>
 <nonFilteredFileExtensions>
 <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
 <nonFilteredFileExtension>woff</nonFilteredFileExtension>
 <nonFilteredFileExtension>woff2</nonFilteredFileExtension>
 </nonFilteredFileExtensions>
 </configuration>
 </plugin>
 </plugins>
</build>

*注意:我们海报用到了字体作为资源文件引入,在经过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;

/**
 * 〈商品分享海报元素及相关参数定义〉<br>
 *
 * @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;

 @Tolerate
 public 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;

/**
 * 〈测试海报〉<br>
 *
 * @author naiqing
 * @Date 2022/1/22
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
public class CommodityPoster2Test {

 @SneakyThrows
 @Test
 public 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"));
 //二维码logo
 BufferedImage 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<CommodityPoster2Pojo> 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/73901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

排课算法小记

输出&#xff1a; 在配置文件(config.txt)中配置:老师&#xff0c;课程&#xff0c;专业班级&#xff0c;课时的信息&#xff0c;运行test.py自动生成对应班级课程表 eg: 专业1&#xff0c;四门课&#xff0c;每门课每周2课时,共8门课 专业2&#xff0c;四门课&#xff0c;每…

springcloud(服务消费及熔断)

目录 1. 服务消费方式 1.1 RestTemplate1.2 feign2. 服务熔断&#xff08;降级&#xff09; 2.1 在微服务架构中服务熔断的必要性2.2 hystrix2.3 hystrix的使用 1. 服务消费方式 1.1 RestTemplate 传统情况下在java代码里访问restful服务&#xff0c;一般使用Apache的HttpClie…

[附源码]JAVA毕业设计田径运动会管理系统(系统+LW)

[附源码]JAVA毕业设计田径运动会管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技…

Vue项目实战 可视化 创建(vue2+Element ui)

Vue项目实战创建项目通过脚手架 创建项目 配置 vue 路由配置 element—ui 组件库配置 axios 库创建远程仓库初始化 git 远程仓库 将本地项目托管到 码云前端项目初始化步骤① 安装vue脚手架② 通过脚手架 创建项目③ 配置 vue 路由④ 配置 element—ui 组件库⑤ 配置 axios 库⑥…

基于小波变换的去噪,带GUI界面,可以设置小波变换层数

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 近年来&#xff0c;小波理论得到了非常迅速的发展&#xff0c;而且由于其具备良好的时频特性&#xff0c;因而实际应用也非常广泛。在去噪领域中&#xff0c;小波理论也同样受到了许多学者的重视…

关于我的Oracle Primavera P6/Unifier/Gateway离线帮助中心

目录 ​编辑 一、前序 二、路子 三、用途 四、最后 一、前序 经常到处飞&#xff0c;很多时候会又比较依赖于网页查看产品的帮助&#xff0c;而网页又比较依赖于网络 怎么办呢 有人提到通过官方提供的PDF&#xff0c;毕竟上面的内容和网页展现几乎完全一样&#xff0c;…

【ChatGPT】与ChatGPT聊天,了解世界杯的前世今生

文章目录&#x1f3c6; 前言&#x1f4ac; 什么是ChatGPT⚽ 与ChatGPT的快问快答&#x1f9e9; 总结&#x1f3c6; 前言 最近火爆全网的chatGPT&#xff0c;吸引一大批技术爱好者的疯狂围观。大家使用过后&#xff0c;纷纷发出惊叹&#xff0c;深陷其中&#xff0c;无法自拔。 …

数字信号处理用脉冲响应不变法和双线性变换法设计巴特沃斯滤波器MATLAB实现——实例

文章目录符号含义例题脉冲响应不变法双线性变换法画图完整代码符号含义 例题 脉冲响应不变法 clear close all clcfs1000;%采样频率 fc200;%通带截止频率 fr300;%阻带截止频率 T0.001; %采样周期%%%%%%%脉冲响应不变法 wp12*pi*fc;%通带截止频率 wr12*pi*fr;%阻带截止频率[N1,…

数据分享|用加性多元线性回归、随机森林、弹性网络模型预测鲍鱼年龄和可视化...

原文链接&#xff1a;http://tecdat.cn/?p24127鲍鱼是一种贝类&#xff0c;在世界许多地方都被视为美味佳肴&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。介绍相关视频养殖者通常会切开贝壳并通过显微镜计算环数来估计鲍鱼的年龄。因此&#xff0c;判断鲍鱼…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.3 初始化数据

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV1qd4y1s7xk 布局完成后&#xff0c;就可以修改控件的名称&#xff0c;以及添加初始化数据 1. 变量命名 先修改各控件显示的的名称&#xff0c;做到 “见名知义”&#xff0c;方便写代码 修改完…

C语言开发《推箱子游戏》,亲自手把手教会大家

【C语言经典算法100道实战题】适合具备C语言基础语法的同学学习&#xff0c;提高编写程序的逻辑思维能力和算法设计能力专门精心设计。100个经典的算法供大家练习及配套对应的录播视频。为我们今后学习其它的编程语言和软件开发打下坚实的基础&#xff0c;让你在编码道路上如鱼…

【手把手】教你玩转消息中间件之RabbitMQ

1、微服务下现存的各种问题 服务调用问题 当两个服务调用时&#xff0c;可以通过传统的HTTP方式&#xff0c;让服务A直接去调用服务B的接口&#xff0c;但是这种方式是同步的方式&#xff0c;虽然可以采用SpringBoot提供的Async注解实现异步调用&#xff0c;但是这种方式无法…

gsva gsea ssgsea gaochao 使用GSVA方法计算某基因集在各个样本的表现

傻傻分不清!GSEA & GSVA有啥差别?史上最全教程来了! - 知乎 (zhihu.com) 文章发表于2013年,GSVA: gene set variation analysis for microarray and RNA-Seq data 同样是broad 研究生出品,其在2005年PNAS发表的gsea已经高达1.4万的引用了,不过这个GSVA才不到300。 G…

【边缘检测】基于模糊算法的图像边缘检测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步进步&#xff0c;matlab项目目标合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信息&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算…

实时数仓Flink生产环境部署+提交作业【步骤】

文章目录1、基础环境2、开发环境2.1、pom.xml2.2、log4j.properties2.3、测试用的代码2.3.1、Kafka工具2.3.3、Flink执行环境工具2.3.3、测试Flink读写Kafka2.3.4、测试FlinkSQL读写Kafka2.4、打包后上传到服务器3、生产环境3.1、Flink安装3.2、Flink on YARN下3种模式3.2.1、S…

Linux下POSIX信号量以及基于环形队列的生产消费模型

目录 一、POSIX信号量介绍 1. 信号量原理 2&#xff0c;初始化信号量 3,信号量销毁 4&#xff0c;信号量等待 5,发布信号量 二&#xff0c;基于环形队列的生产消费模型 1.基于单线程 2&#xff0c;测试&#xff1a; 3&#xff0c;基于多线程 4,测试 三&#xff0c;代…

故障转移,服务发现,负载均衡所运用的连接池

没错&#xff0c;说的就是连接池&#xff0c;玩互联网架构&#xff0c;连接池是必须要掌握的。 什么是连接池&#xff1f; 创建与管理连接缓冲池的技术&#xff0c;本质是资源复用&#xff0c;不用频繁创建与销毁连接&#xff0c;能提高性能。 画外音&#xff1a;数据库连接池…

Sentinel-2 L2A数据导入ENVI

Sentinel-2 L2A数据导入ENVI前言0 首先对SNAP进行设置1 用SNAP对Sentinel-2数据重采样2 在ENVI中打开重采样后的Sentinel-2数据3 其实不用重采样也行&#xff0c;ENVI可以直接打开解压后的Ssentinel-2文件&#xff0c;只需要将解压后的MTD_MSIL2A.xml拖进ENVI即可前言 Sentine…

揭秘倚天实例背后的硬核实力

2022云栖大会&#xff0c;阿里巴巴宣布自研CPU倚天710已大规模应用&#xff0c;阿里云未来两年20%的新增算力将使用自研CPU。11月15日&#xff0c;倚天710云实例上线并正式进入大规模应用阶段&#xff0c;现已应用于阿里巴巴集团核心业务&#xff0c;并服务科学研究、智能手机行…

[附源码]JAVA毕业设计天津城建大学校友录管理系统(系统+LW)

[附源码]JAVA毕业设计天津城建大学校友录管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。…