精美的海报通常都是由UI进行精心设计的,现在有100 件商品需要进行宣传推广,如果每个商品都出一张图显然是不合理的,且商品信息各异。因此需要通过代码的形式生成海报。对此,我也对我宣传一波,企图实现我一夜暴富的伟大宏图。
生成的海报放在最前面,扫描下方二维码,手机上更好的实时阅读小咸鱼的技术窝。
代码实现
需要的依赖
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
完整Java 代码
需要你准备一张背景图、封面图、二维码图、以及对应的文字描述,我这里全部搞成静态的了。各位织入自己的业务即可。用到的技术是 Graphics2D。我们使用的时候只需要知道三个概念就行。
- x 坐标:横坐标
- y 坐标:纵坐标
- width:坐标点向右,的宽度
- height:坐标点向下的,高度
为了保证图片的美观性,你需要去向 ui 询问,字体的配色参数、图片的尺寸参数。然后进行排版。里面需要自己去理解一下,都是些数学加减法的计算。这里不过多 bb。本文海报用到的图片尺寸是 610*633 的。
public class ImageUtils {
public static String createPoster(String content) throws Exception {
if (content.length() > 300) {
content = StringUtils.substring(content, 0, 300) + "...";
}
//封面
File petImg = new File("/Users/zhangzixing/Desktop/temp/fm.jpg");
//二维码图片
File qrCodeImg = new File("/Users/zhangzixing/Desktop/temp/ewm.png");
//背景地址
URL url = ImageUtils.class.getResource("/image/bj1.jpg");
File fileBg = FileUtils.toFile(url);
FileInputStream fis = new FileInputStream(fileBg);
Image srcImg = ImageIO.read(fis);
BufferedImage bufferedImage = new BufferedImage(
srcImg.getWidth(null),
srcImg.getHeight(null),
BufferedImage.TYPE_INT_RGB);
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
Graphics2D g = bufferedImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(srcImg.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
//内容
Graphics2DUtils.drawString(g, Color.decode("#323232"),
new Font("PingFang SC Bold",
Font.BOLD, 30),
content,
100, 640, 500, 30, 10, false);
BufferedImage read = ImageIO.read(qrCodeImg);
//扫一扫
Graphics2DUtils.drawString(g, Color.decode("#323232"),
new Font("PingFang SC Bold", Font.BOLD, 70),
"扫一扫",
width - read.getWidth() / 2 - 200, height - 70,
width - 20,
20, 10, false);
//二维码
g.drawImage(ImageIO.read(qrCodeImg), width - read.getWidth() - 100, height - read.getHeight() - 150, read.getWidth(), read.getHeight(), null);
//封面
g.drawImage(ImageIO.read(petImg), 20, 20, width - 40, height - 900, null);
g.dispose();
ByteArrayOutputStream os = new ByteArrayOutputStream();
ImageIO.write(bufferedImage, "jpg", os);
String encodeStr = Base64.getEncoder().encodeToString(os.toByteArray());
FileUtils.writeByteArrayToFile(new File("/Users/zhangzixing/Desktop/temp/海报.jpg"), os.toByteArray());
fis.close();
os.close();
return encodeStr;
}
//610*633
public static void main(String[] args) throws Exception {
System.err.println(createPoster("22 届本科毕业生,擅长Spring 全家桶源码、Mybatis 源码、常见设计模式使用、Redis 各大数据类型使用、Java 常用并发包源码、Spring Cloud 全家桶、RocketMq 使用"));
}
}
用到的工具类
import org.apache.commons.lang3.StringUtils;
import java.awt.*;
import java.util.ArrayList;
public final class Graphics2DUtils {
/**
* 向画布上写文字
*
* @param g Graphics2D对象
* @param color 颜色
* @param font 字体
* @param content 内容
* @param x 坐标x
* @param y 坐标y
*/
public static void drawString(Graphics2D g, Color color, Font font, String content, float x, float y) {
g.setColor(color);
g.setFont(font);
g.drawString(content, x, y);
}
/**
* 向画布上写多行文字文字,自动居中
*
* @param g Graphics2D对象
* @param color 颜色
* @param font 字体
* @param content 内容
* @param x 坐标X
* @param y 坐标y
* @param width 画布宽度
* @param lineWordNum 每行字数
* @param linePadding 行间距
* @param center 是否居中
*/
public static void drawString(Graphics2D g, Color color, Font font, String content, float x, float y, int width, int lineWordNum, int linePadding, boolean center) {
int num = content.length();
ArrayList<String> contents = new ArrayList<String>();
if (num <= lineWordNum) {
contents.add(content);
} else {
for (int i = 0; i < num; i += lineWordNum) {
contents.add(StringUtils.substring(content, i, i + lineWordNum));
}
}
for (int i = 0; i < contents.size(); i++) {
String s = contents.get(i);
if (i != 0) {
y += linePadding + font.getSize();
}
if (center) {
drawCenterString(g, color, font, s, width, y);
} else {
drawString(g, color, font, s, x, y);
}
}
}
/**
* 向画布上写多行文字文字,自动居中
*
* @param g Graphics2D对象
* @param color 颜色
* @param font 字体
* @param content 内容
* @param y 坐标y
* @param width 画布宽度
* @param lineWordNum 每行字数
* @param linePadding 行间距
*/
public static void drawCenterString(Graphics2D g, Color color, Font font, String content, float y, int width, int lineWordNum, int linePadding) {
drawString(g, color, font, content, 0, y, width, lineWordNum, linePadding, true);
}
/**
* 向画布上写文字,自动居中
*
* @param g Graphics2D对象
* @param color 颜色
* @param font 字体
* @param content 内容
* @param width 画布宽度
* @param y 坐标y
*/
public static void drawCenterString(Graphics2D g, Color color, Font font, String content, int width, float y) {
int textWidth = getStringWidth(g, font, content);
drawString(g, color, font, content, (width - textWidth) / 2, y);
}
/**
* 获取字符串内容的宽度
*
* @param g Graphics2D对象
* @param font 字体
* @param content 内容
* @return
*/
public static int getStringWidth(Graphics2D g, Font font, String content) {
FontMetrics fm = g.getFontMetrics(font);
//获取字符串宽度
return fm.stringWidth(content);
}
}
总结
关注不迷路,这里是小咸鱼的技术窝