package com.linkwechat.common.utils; import cn.hutool.core.codec.Base64; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.google.zxing.*; import com.google.zxing.client.j2se.BufferedImageLuminanceSource; import com.google.zxing.client.j2se.MatrixToImageConfig; import com.google.zxing.client.j2se.MatrixToImageWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.HybridBinarizer; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.springframework.stereotype.Component; import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.Hashtable; /** * @version * @Description: 生成二维码的工具类型 */ @Component public class QrCodeGenerator { private static final String DEFAULT_CHAR_SET = "UTF-8"; private static final String DEFAULT_FORMAT_NAME = "JPG"; private static String EXCEL_PATH = "QRCode/"; private static String UPLOAD_PATH = "/upload/QRCode/"; // 二维码宽度 private static final int DEFAULT_QR_CODE_WIDTH = 200; // 二维码高度 private static final int DEFAULT_QR_CODE_HEIGHT = 200; /** * 创建BitMatrix比特矩阵 * @Date 2023/09/24 22:29 * @Param contents 二维码里的内容 * @Param width 二维码宽度 * @Param height 二维码高度 * @return com.google.zxing.common.BitMatrix */ public static BitMatrix createBitMatrix(String contents, int width, int height) throws WriterException, IOException { if (ObjectUtil.isNull(width)) { width = DEFAULT_QR_CODE_WIDTH; } if (ObjectUtil.isNull(height)) { height = DEFAULT_QR_CODE_HEIGHT; } Hashtable hints = new Hashtable(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 纠错等级L,M,Q,H hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET); // 编码utf-8 hints.put(EncodeHintType.MARGIN, 1); // 边距 // 创建比特矩阵 BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints); return bitMatrix; } /** * 创建二维码,返回字节数组 * @Date 2023/09/24 22:30 * @Param contents 二维码里的内容 * @Param imageFormat 图片后缀名 * @Param width 二维码宽度 * @Param height 二维码高度 * @return byte[] */ public static byte[] createQrCode(String contents, String imageFormat, int width, int height) throws WriterException, IOException { if (StrUtil.isBlank(imageFormat)) { imageFormat = DEFAULT_FORMAT_NAME; } BitMatrix bitMatrix = createBitMatrix(contents, width, height); ByteArrayOutputStream os = new ByteArrayOutputStream(); MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, os); return os.toByteArray(); } /** * 创建二维码,返回base64字符串 * @Date 2023/09/24 22:30 * @Param contents 二维码里的内容 * @Param imageFormat 图片后缀名 * @Param width 二维码宽度 * @Param height 二维码高度 * @return byte[] */ public static String createQrCodeBase64(String contents, String imageFormat, int width, int height) throws WriterException, IOException { byte[] bytes = createQrCode(contents, imageFormat, width, height); return Base64.encode(bytes); } /** * 解码二维码 * @Date 2023/09/24 22:32 * @Param [image] * @return java.lang.String */ public static String decodeQrCode(BufferedImage image) throws Exception { if (image == null) return StrUtil.EMPTY; BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image); BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); Hashtable hints = new Hashtable(); hints.put(DecodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET); Result result = new MultiFormatReader().decode(bitmap, hints); return result.getText(); } /** * 转换为BufferedImage * @Date 2023/09/24 22:32 * @Param [bitMatrix] * @return java.awt.image.BufferedImage */ public static BufferedImage toBufferedImage(BitMatrix bitMatrix) throws IOException, WriterException { MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF); BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, matrixToImageConfig); return bufferedImage; } /** * 给二维码添加logo * @Date 2023/09/24 22:33 * @Param [bufferedImage, logoFile] * @return java.awt.image.BufferedImage */ public static BufferedImage addQrCodeLogo(BufferedImage bufferedImage, File logoFile) throws IOException { Graphics2D graphics = bufferedImage.createGraphics(); int matrixWidth = bufferedImage.getWidth(); int matrixHeigh = bufferedImage.getHeight(); // 读取logo图片文件 BufferedImage logo = ImageIO.read(logoFile); int logoWidth = logo.getWidth(); int logoHeight = logo.getHeight(); // 计算logo放置位置 int x = bufferedImage.getWidth() / 5 * 2; int y = bufferedImage.getHeight() / 5 * 2; int width = matrixWidth / 5; int height = matrixHeigh / 5; // 开始绘制图片 graphics.drawImage(logo, x, y, width, height, null); graphics.drawRoundRect(x, y, logoWidth, logoHeight, 15, 15); graphics.setStroke(new BasicStroke(5.0F, 1, 1)); graphics.setColor(Color.white); graphics.drawRect(x, y, logoWidth, logoHeight); graphics.dispose(); bufferedImage.flush(); return bufferedImage; } /** * @version * @author: hxl * @Date: 2024/8/13 17:55 * @Description: 返回二维码图片路径 */ public static String getQrCode(String orderNo, String url, String uploadPath) { BufferedImage bufferedImage = null; String fileName = orderNo + "_" + "_rwm.jpg"; // 修复文件名生成逻辑 String saveFilePath = uploadPath + "/" + EXCEL_PATH + fileName; String resultPath = "/" + EXCEL_PATH + fileName; // 返回相对路径 // 创建File对象 File dir = new File(uploadPath + File.separator + EXCEL_PATH).getAbsoluteFile(); // 获取绝对路径 // 判断目录是否存在 if (!dir.exists() && !dir.mkdirs()) { throw new RuntimeException("目录不存在或创建失败,请重试!!"); } try { bufferedImage = toBufferedImage(createBitMatrix(url, 300, 300)); ImageIO.write(bufferedImage, "jpg", new File(saveFilePath)); // 修改为"jpg"以匹配文件名 } catch (Exception e) { throw new RuntimeException("转为二维码报错,请重试!!", e); } return resultPath; } }