二维码合图,是为二维码套上一个好看的模版底图,再配上一定的文案,这种图片常见于线下地推业务中,例如扫码领鸡蛋等场景~ 下面是如何得到这个图片
生成二维码
二维码的本质是一个url,通过二维码插件szxing就可以得到一个二维码
pom文件
<dependency>
<groupId>com.taobao.xcode.szxing</groupId>
<artifactId>szxing</artifactId>
</dependency>
生成二维码java核心代码
// 要生成二维码的url
String url="http://taobao.com";
// 二维码的宽
int width = 248;
// 二维码的高
int height = 252;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// 通过QRCodeWriter.encode生成的输出流
QRCodeWriter.encode(url, width, height, null, byteArrayOutputStream);
// 根据 QRCodeWriter.encode生成的输出流,生成BufferedImage
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
BufferedImage qrImage = ImageIO.read(byteArrayInputStream);
// 根据BufferedImage,生成图片文件
File file = new File();
ImageIO.write(qrImage, "jpg", file);
通过跑代码,可以得到一个二维码
二维码合图
一般二维码都会有一个漂亮的模版,并且会有些文字描述,如下图,图1是模版,图2是根据模版合图后的图,且“淘宝福利码”上方有一个很小的说明。接下来将这是如何实现的,我是通过java.awt包下的Graphics2D工具实现的,主要思路是,可以把Graphics2D理解成一个画板,以模版图片为画板的底图,把二维码图片贴到画板中间合适位置(主要是调整x轴、y轴坐标),再把要加的文字贴到合适的位置。
以下是代码实现
ImageUtil工具类
public class ImageUtil {
/**
* 合图
*
* @param drawBoardDTO 画板
* @param templatePositionDTO 合图模版
* @param masterImagePositionDTO 主图
* @param imageTexts 合图文案
* @return
*/
public static BufferedImage drawImageBase(DrawBoardDTO drawBoardDTO, ImagePositionDTO templatePositionDTO,
ImagePositionDTO masterImagePositionDTO, java.util.List<ImageText> imageTexts) {
// RGB形式
BufferedImage bgBufImage = new BufferedImage(drawBoardDTO.getWidth(), drawBoardDTO.getHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics2D bgBufImageGraphics = bgBufImage.createGraphics();
// 设置背景色
bgBufImageGraphics.setBackground(drawBoardDTO.getBackgroundColor());
// 通过使用当前绘图表面的背景色进行填充来清除指定的矩形
bgBufImageGraphics.clearRect(0, 0, drawBoardDTO.getWidth(), drawBoardDTO.getHeight());
// 画模版
bgBufImageGraphics.drawImage(templatePositionDTO.getBufferedImage(), templatePositionDTO.getX(),
templatePositionDTO.getY(), templatePositionDTO.getWidth(), templatePositionDTO.getHeight(), null);
// 画主图
bgBufImageGraphics.drawImage(masterImagePositionDTO.getBufferedImage(), masterImagePositionDTO.getX(),
masterImagePositionDTO.getY(), masterImagePositionDTO.getWidth(), masterImagePositionDTO.getHeight(), null);
// 设置画笔,设置Paint属性
// 抗锯齿
bgBufImageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
bgBufImageGraphics.setPaint(Color.WHITE);
// 画文案
for (ImageText imageText : imageTexts) {
bgBufImageGraphics.setFont(imageText.getFont());
if (Objects.nonNull(imageText.getColor())) {
bgBufImageGraphics.setColor(imageText.getColor());
}
// 计算文字长度,计算居中的x点坐标
Integer x = imageText.getX();
if (Objects.isNull(x)) {
FontMetrics fm = bgBufImageGraphics.getFontMetrics(imageText.getFont());
int textWidth = fm.stringWidth(imageText.getData());
x = (drawBoardDTO.getWidth() - textWidth) / 2;
}
bgBufImageGraphics.drawString(imageText.getData(), x, imageText.getY());
}
bgBufImageGraphics.dispose();
return bgBufImage;
}
}
DrawBoardDTO类 画板类(画板宽高、背景颜色等)
@Data
@AllArgsConstructor
public class DrawBoardDTO {
// 画板的宽
private int width;
// 画板的高
private int height;
// 画板的背景颜色
private Color backgroundColor;
}
ImagePositionDTO类 图片位置类(即二维码在画板的坐标)
@Data
@AllArgsConstructor
public class ImagePositionDTO {
// 图片信息
private BufferedImage bufferedImage;
// 二维码x坐标位置
private int x;
// 二维码y坐标位置
private int y;
// 二维码宽度
private int width;
// 二维码高度
private int height;
}
ImageText类 文案信息(文案描述、文案横纵坐标、字体、颜色等)
@Data
@Builder
public class ImageText {
// 实际文本
private String data;
// 文本x坐标位置, 填null则表示水平居中
private Integer x;
// 文本y坐标位置
private Integer y;
// 字体
private Font font;
// 颜色
private Color color;
public ImageText(String data, Integer y, Font font) {
this.data = data;
this.y = y;
this.font = font;
}
public ImageText(String data, Integer x, Integer y, Font font, Color color) {
this.data = data;
this.x = x;
this.y = y;
this.font = font;
this.color = color;
}
}
使用ImageUtil.drawImageBase实现合图的调用
// 二维码的在oss上的url
String qrOssUrl="";
BufferedImage bufferedImage = null;
try {
// 定义画板
DrawBoardDTO drawBoardDTO = new DrawBoardDTO(672, 1264, Color.WHITE);
// 定义合图模版
InputStream InputStream = ImageUtil.class.getResourceAsStream("/newBenefitCodeTemplate.jpg");
ImagePositionDTO templatePositionDTO = new ImagePositionDTO(ImageIO.read(InputStream), 0, 0, 672,
1264);
// 定义主图
ImagePositionDTO qrPositionDTO = new ImagePositionDTO(ImageIO.read(new URL(qrOssUrl)),
90, 430, 500, 500);
// 定义合图文案
List<ImageText> imageTexts = Lists.newArrayList(
new ImageText("PromoterID:XXX", 150, new Font("宋体", Font.PLAIN, 15)),
new ImageText("PromoterID:YYY", 150, new Font("阿里巴巴普惠体", Font.PLAIN, 20)),
);
bufferedImage = ImageUtil.drawImageBase(drawBoardDTO, templatePositionDTO, qrPositionDTO, imageTexts);
} catch (Throwable throwable) {
// 记录日志
}
字体安装
在图片上写文案的时候,可以设置漂亮的字体,以下是服务器安装字体的说明,以下是几个的字体包(阿里巴巴普惠体)
[文件: Alibaba-PuHuiTi-Bold.ttf] 请在PC端预览或下载
[文件: Alibaba-PuHuiTi-Heavy.ttf] 请在PC端预览或下载
[文件: Alibaba-PuHuiTi-Light.ttf] 请在PC端预览或下载
[文件: Alibaba-PuHuiTi-Medium.ttf] 请在PC端预览或下载
[文件: Alibaba-PuHuiTi-Regular.ttf] 请在PC端预览或下载