先说下需求:
做一个推广项目,根据访问url生成二维码,用户通过识别二维码就可以访问应用。
二维码生成,前端和后端都可以生成。前端通过:qrcode.js,可以自行百度。
我这边主要记录下Java生成二维码的步骤:
- 创建二维码矩阵信息
- 生成二维码图片
- 二维码中心添加logo
- 将二维码写入背景图片
下图就是生成好
二维码:
带logo二维码:
加背景的二维码:
代码如下:(**ImageIo读取图片流可能会造成图片出现颜色失真,自行百度处理**)
package cn.medbanks.backend.market.center.biz.common.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import org.springframework.core.io.ClassPathResource;
import lombok.extern.slf4j.Slf4j;
/**
* 二维码生成工具类
* @author huaxiaozhou
* @since 2019-11-26 09:56
*/
@Slf4j
public class QRCodeUtils {
private static final int BLACK = 0xFF000000;//黑色
private static final int WHITE = 0xFFFFFFFF;//白色
private static final int margin = 0;//边框
private static final int LogoPart = 4;//
/**
* 生成二维码矩阵信息
*
* @param url 二维码图片内容
* @param width 二维码图片宽度
* @param height 二维码图片高度
*/
public static BitMatrix setBitMatrix(String url, int width, int height) {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小
BitMatrix bitMatrix = null;
try {
bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height, hints);
} catch (WriterException e) {
e.printStackTrace();
}
return bitMatrix;
}
/**
* 生成二维码图片
*
* @param matrix 二维码矩阵信息
*/
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
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;
}
/**
* 在二维码图片中添加logo图片
*
* @param image 二维码图片
* @param logoLocation logo图片
*/
public static BufferedImage addLogo(BufferedImage image, String logoLocation) throws IOException {
Graphics2D g = image.createGraphics();
BufferedImage logoImage = getClassPathResource(logoLocation);
// 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
int height = width;
// 计算logo图片放置位置
int x = (image.getWidth() - width) / 2;
int y = (image.getHeight() - height) / 2;
// 在二维码图片上绘制logo图片
g.drawImage(logoImage, x, y, width, height, null);
// 绘制logo边框,可选
// g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10);
g.setStroke(new BasicStroke(2)); // 画笔粗细
//g.setColor(Color.WHITE); // 边框颜色
g.drawRect(x, y, width, height); // 矩形边框
logoImage.flush();
g.dispose();
return image;
}
/**
* 将二维码图片画到背景图片里
* zhouxiaoyu.add 20191127
*
* @param image 二维码图片
* @param bgLocation 背景图片路径
*/
public static BufferedImage addQRImage(BufferedImage image, String bgLocation) throws IOException {
//1.获取背景图片BufferedImage
BufferedImage BGImage = getBufferedImage(bgLocation);
//2.将二维码画入背景图片中
Graphics2D g = BGImage.createGraphics();//创建画板对象
int x = (BGImage.getWidth() - image.getWidth()) / 2;
int y = BGImage.getHeight() / 4;//设置画板纵坐标,高度的1/4
/**
* 二维码长度为横坐标4/6的长度, x+10,居中显示
* 二维码的高度为纵坐标2/4,y+10:文案空出一点距离
*/
g.drawImage(image, x, y + 10, image.getWidth(), image.getHeight(), null);
BGImage.flush();
g.dispose();
return BGImage;
}
/**
* 获取 ClassPathResource 下图片
* @param resouceLocation
* @return
* @throws IOException
*/
private static BufferedImage getClassPathResource(String resouceLocation) throws IOException {
ClassPathResource cpr = new ClassPathResource(resouceLocation);
return ImageIO.read(cpr.getInputStream());
}
/**
* 拷贝新图片,解决流颜色失真
* @param resouceLocation
* @return
* @throws IOException
*/
private static BufferedImage getBufferedImage(String resouceLocation) throws IOException {
BufferedImage img = getClassPathResource(resouceLocation);
BufferedImage newImg = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
newImg.getGraphics().drawImage(img, 0, 0, null);
return newImg;
}
}