import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 生成二维码图片
*
* @author Mr丶s
* @date 2024/8/25 下午10:54
* @description
*/
public class QRCodeGeneratorUtils {
/**
* 生成二维码图片
*
* @param content 二维码内容
* @param width 二维码宽度
* @param height 二维码高度
* @param logoPath 中心 logo 路径,可为 null
* @param bgImagePath 背景图片路径,可为 null
* @return 二维码图片的字节数组
* @throws Exception 异常信息
*/
public static byte[] generateQRCodeImage(String content,
int width,
int height,
String logoPath,
String bgImagePath) {
// 配置二维码的参数
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, 1);
// 输出为字节数组
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
// 生成二维码矩阵
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
// 将矩阵转为图片
BufferedImage qrImage = MatrixToImageWriter.toBufferedImage(bitMatrix, new MatrixToImageConfig());
// 如果提供了背景图片,则将背景图片与二维码合成
if (bgImagePath != null) {
BufferedImage bgImage = ImageIO.read(new File(bgImagePath));
qrImage = overlayImages(bgImage, qrImage);
}
// 如果提供了中心 logo,则将 logo 叠加在二维码中
if (logoPath != null) {
BufferedImage logoImage = ImageIO.read(new File(logoPath));
qrImage = addLogoToQRCode(qrImage, logoImage);
}
ImageIO.write(qrImage, "png", outputStream);
} catch (WriterException | IOException e) {
throw new RuntimeException(e);
}
return outputStream.toByteArray();
}
/**
* 将两个图片进行叠加
*
* @param bgImage 背景图片
* @param qrImage 二维码图片
* @return 叠加后的图片
*/
private static BufferedImage overlayImages(BufferedImage bgImage, BufferedImage qrImage) {
int width = Math.max(bgImage.getWidth(), qrImage.getWidth());
int height = Math.max(bgImage.getHeight(), qrImage.getHeight());
BufferedImage combined = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = combined.createGraphics();
g.drawImage(bgImage, 0, 0, null);
g.drawImage(qrImage, (width - qrImage.getWidth()) / 2, (height - qrImage.getHeight()) / 2, null);
g.dispose();
return combined;
}
/**
* 为二维码添加 logo
*
* @param qrImage 二维码图片
* @param logoImage logo 图片
* @return 添加 logo 后的二维码图片
*/
private static BufferedImage addLogoToQRCode(BufferedImage qrImage, BufferedImage logoImage) {
Graphics2D g = qrImage.createGraphics();
int logoWidth = qrImage.getWidth() / 5;
int logoHeight = logoImage.getHeight() * logoWidth / logoImage.getWidth();
int x = (qrImage.getWidth() - logoWidth) / 2;
int y = (qrImage.getHeight() - logoHeight) / 2;
g.drawImage(logoImage, x, y, logoWidth, logoHeight, null);
// 设置圆角边框
BasicStroke stroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g.setStroke(stroke);
RoundRectangle2D.Float round = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 20, 20);
g.setColor(Color.WHITE);
g.draw(round);
g.dispose();
return qrImage;
}
}
05-02
4072