效果图
第一步:生成自定义的二维码
1 导入依赖
<!-- 二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.2.1</version>
</dependency>
<!-- 二维码 end-->
2 二维码工具类
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import javax.imageio.ImageIO;
import javax.swing.filechooser.FileSystemView;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
/**
* 喷二维码
* @Author: zhangYuHui
* @Date: 2020/4/21 15:31
*/
public class QrCodeUtil {
/**
* 生成二维码
* @param url 参数路径
* @param fileName 文件名称
* @return
*/
public static String createQrCode(String url,String fileName) {
//生成的地址
String path = FileSystemView.getFileSystemView().getHomeDirectory() + File.separator + "testQrcode";
try {
Map<EncodeHintType, String> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, 220, 220, hints);
File file = new File(path, fileName);
if (file.exists() || ((file.getParentFile().exists() || file.getParentFile().mkdirs()) && file.createNewFile())) {
writeToFile(bitMatrix, "png", file);
return file.getPath();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
static void writeToFile(BitMatrix matrix, String format, File file) throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, file)) {
throw new IOException("Could not write an image of format " + format + " to " + file);
}
}
static void writeToStream(BitMatrix matrix, String format, OutputStream stream) throws IOException {
BufferedImage image = toBufferedImage(matrix);
if (!ImageIO.write(image, format, stream)) {
throw new IOException("Could not write an image of format " + format);
}
}
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
/**
* 生成内容
* @param matrix
* @return
*/
private static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
}
}
return image;
}
}
第二步,生成海报工具类
import com.xcds.shequ.common.constant.Constants;
import com.xcds.shequ.project.promote.entity.GoodsInfoVO;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
/**
* 图片生成海报
* @Author: zhangYuHui
* @Date: 2020/7/1 17:52
*/
public class ImgUtils {
public static final String IMAGE_SUFFIX = ".png";
/**
* 合成图片
* @param bgImgUrl 背景图(可以自定义背景)
* @param headImgUrl 天猫,淘宝,pdd 小图标,
* @param goodsInfoVO 商品集合
* @return url
* @throws IOException
*/
public static String drawImage(InputStream bgImgUrl,InputStream headImgUrl,GoodsInfoVO goodsInfoVO) throws IOException {
int width = 620;
int height = 1004;
// RGB形式,自定义背景
// BufferedImage bgBufImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
BufferedImage bgBufImage = ImageIO.read(bgImgUrl);
Graphics2D bgBufImageGraphics = bgBufImage.createGraphics();
// 设置背景色
bgBufImageGraphics.setBackground(Color.WHITE);
// 通过使用当前绘图表面的背景色进行填充来清除指定的矩形。
// bgBufImageGraphics.clearRect(0, 0, width, height);
// 设置画笔,设置Paint属性 ==>设置标题文字
bgBufImageGraphics.setPaint(Color.black);
Font font = new Font("PingFangSC-Medium", Font.BOLD, 28);
bgBufImageGraphics.setFont(font);
//商品标题,大于23个子,用点代替
String title = goodsInfoVO.getTitle();
if(title.length()>22){
title=title.substring(0,21)+"...";
}
bgBufImageGraphics.drawString(title, 70, 80);
// 设置卷后价
Font font1 = new Font("PingFangSC-Medium", Font.BOLD, 60);
bgBufImageGraphics.setPaint(Color.red);
bgBufImageGraphics.setFont(font1);
bgBufImageGraphics.drawString(goodsInfoVO.getOrgPrice(), 160, 180);
//获取上次的文字宽度 + 上一次的x轴+ 隔离距离
FontMetrics fm = bgBufImageGraphics.getFontMetrics(font1);
int width1 = fm.stringWidth(goodsInfoVO.getOrgPrice())+165;
// 设置原价后价
HashMap<TextAttribute,Object> hm = new HashMap<>(Constants.MAP_LENG);
hm.put(TextAttribute.FAMILY,"PingFangSC-Medium");
hm.put(TextAttribute.SIZE, 28);
hm.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
//粗体
hm.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
//删除线
hm.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);
Font font2 = new Font(hm);
bgBufImageGraphics.setPaint(Color.lightGray);
bgBufImageGraphics.setFont(font2);
bgBufImageGraphics.drawString("原价¥"+goodsInfoVO.getPrice(), width1, 180);
// 设置购买人数
Font font3 = new Font("PingFangSC-Medium", Font.BOLD, 20);
bgBufImageGraphics.setPaint(Color.gray);
bgBufImageGraphics.setFont(font3);
bgBufImageGraphics.drawString(goodsInfoVO.getMonthSales()+" 人已买", 60, 220);
// 设置优惠卷金额
Font font4 = new Font("PingFangSC-Medium", Font.BOLD, 30);
bgBufImageGraphics.setPaint(Color.white);
bgBufImageGraphics.setFont(font4);
bgBufImageGraphics.drawString("¥"+goodsInfoVO.getCouponPrice(), 580, 190);
// 抗锯齿
bgBufImageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// BufferedImage posterBufImage = ImageIO.read(new URL(posterImgUrl));
// //直接使用图片做背景,自定义背景使用上面方式
// Graphics2D posterBufImageGraphics = posterBufImage.createGraphics();
//商品图片
BufferedImage posterBufImage = ImageIO.read(new URL(goodsInfoVO.getPicUrl()));
//读取本地图片 二维码
BufferedImage qrCodeImage = ImageIO.read(new FileInputStream(goodsInfoVO.getQrCodeImgUrl()));
//标识图片,天猫
BufferedImage headImage = ImageIO.read(headImgUrl);
// 设置圆形图片
BufferedImage roundHeadImg = new BufferedImage(headImage.getWidth(), headImage.getHeight(),
BufferedImage.TYPE_INT_RGB);
Graphics2D roundHeadGraphics = roundHeadImg.createGraphics();
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, roundHeadImg.getWidth(), roundHeadImg.getHeight());
roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
roundHeadImg = roundHeadGraphics.getDeviceConfiguration().createCompatibleImage(headImage.getWidth(),
headImage.getHeight(), Transparency.TRANSLUCENT);
roundHeadGraphics = roundHeadImg.createGraphics();
// 使用 setRenderingHint 设置抗锯齿
roundHeadGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
roundHeadGraphics.setClip(shape);
roundHeadGraphics.drawImage(headImage, 0, 0, null);
roundHeadGraphics.dispose();
// bgBufImageGraphics.drawImage(qrCodeImage, (posterBufImage.getWidth()
// - qrCodeImage.getWidth()), 10, qrCodeImage.getWidth(),
// qrCodeImage.getHeight(), null);
// posterBufImageGraphics.drawImage(roundHeadImg, 50, 100,
// HEAD_URL_WIDTH, HEAD_URL_HEIGHT, null);
//二维码
bgBufImageGraphics.drawImage(qrCodeImage, 520, 970, 220, 210, null);
//天猫图片
bgBufImageGraphics.drawImage(roundHeadImg, 32, 45, 30, 30, null);
//商品图片
bgBufImageGraphics.drawImage(posterBufImage, 32, 250, 680, 680, null);
bgBufImageGraphics.dispose();
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ImageOutputStream imgOut = ImageIO.createImageOutputStream(bs);
ImageIO.write(bgBufImage, "png", imgOut);
// 上传到服务器上
String url = QiniuCloudUtil.uploadObject2OSS(bs.toByteArray());
//字节写入到本地
//QiniuCloudUtil.uploadImgLocalHost(bs.toByteArray());
return url;
}
}
3 接收参数的实体
package com.xcds.shequ.project.promote.entity;
import lombok.Data;
/**
* @Author: zhangYuHui
* @Date: 2020/7/1 17:56
*/
@Data
public class GoodsInfoVO {
/**商品id*/
private String id;
/**用户渠道id*/
private String rid;
/**标题*/
private String title;
/**商品图片*/
private String picUrl;
/**标识,tm 天猫,tb 淘宝,pdd 拼多多*/
private String from;
/**原价*/
private String price;
/**卷后价*/
private String orgPrice;
/**售量*/
private String monthSales;
/**优惠卷价格*/
private String couponPrice;
/**二维码图片*/
private String qrCodeImgUrl;
}
4调用方法
/**
* 生成海报
* @param goodsInfoVO
* @return
*/
@GetMapping("poster")
public AjaxResult poster(GoodsInfoVO goodsInfoVO) throws IOException {
SysUser user = getUser();
if(StringUtils.isNotEmpty(user.getRelationId())){
//生成二维码
String qrCode = QrCodeUtil.createQrCode("www.baidu.com", "temp.jpg");
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("static/app/imgs/"+goodsInfoVO.getFrom()+".png");
InputStream bgImg = this.getClass().getClassLoader().getResourceAsStream("static/app/imgs/bg.png");
goodsInfoVO.setQrCodeImgUrl(qrCode);
String url = ImgUtils.drawImage(bgImg,inputStream,goodsInfoVO);
System.out.println("二维码:"+qrCode+"清除:"+ FileUtils.deleteFile(qrCode));
//成功之后,删除临时二维码文件
return AjaxResult.success(url);
}
return AjaxResult.error("请绑定渠道");
}
注意:这个只是小图标和背景图,
背景图片,相当于填空题一样,把对应的参数填入到指定的地方
postman测试
部署到linux 环境图片文字可能会乱码,需要linux安装正确的字体,参考博客https://blog.youkuaiyun.com/weixin_30292745/article/details/98614816?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
底图加平方字体下载
链接:https://pan.baidu.com/s/1VzfC-7aR079m8SJQ64worQ
提取码:oais