QrCodeGenerator.java 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. package com.linkwechat.common.utils;
  2. import cn.hutool.core.codec.Base64;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.google.zxing.*;
  6. import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
  7. import com.google.zxing.client.j2se.MatrixToImageConfig;
  8. import com.google.zxing.client.j2se.MatrixToImageWriter;
  9. import com.google.zxing.common.BitMatrix;
  10. import com.google.zxing.common.HybridBinarizer;
  11. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
  12. import org.springframework.stereotype.Component;
  13. import javax.imageio.ImageIO;
  14. import java.awt.*;
  15. import java.awt.image.BufferedImage;
  16. import java.io.ByteArrayOutputStream;
  17. import java.io.File;
  18. import java.io.IOException;
  19. import java.util.Hashtable;
  20. /**
  21. * @version
  22. * @Description: 生成二维码的工具类型
  23. */
  24. @Component
  25. public class QrCodeGenerator {
  26. private static final String DEFAULT_CHAR_SET = "UTF-8";
  27. private static final String DEFAULT_FORMAT_NAME = "JPG";
  28. private static String EXCEL_PATH = "QRCode/";
  29. private static String UPLOAD_PATH = "/upload/QRCode/";
  30. // 二维码宽度
  31. private static final int DEFAULT_QR_CODE_WIDTH = 200;
  32. // 二维码高度
  33. private static final int DEFAULT_QR_CODE_HEIGHT = 200;
  34. /**
  35. * 创建BitMatrix比特矩阵
  36. * @Date 2023/09/24 22:29
  37. * @Param contents 二维码里的内容
  38. * @Param width 二维码宽度
  39. * @Param height 二维码高度
  40. * @return com.google.zxing.common.BitMatrix
  41. */
  42. public static BitMatrix createBitMatrix(String contents, int width, int height) throws WriterException, IOException {
  43. if (ObjectUtil.isNull(width)) {
  44. width = DEFAULT_QR_CODE_WIDTH;
  45. }
  46. if (ObjectUtil.isNull(height)) {
  47. height = DEFAULT_QR_CODE_HEIGHT;
  48. }
  49. Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
  50. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 纠错等级L,M,Q,H
  51. hints.put(EncodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET); // 编码utf-8
  52. hints.put(EncodeHintType.MARGIN, 1); // 边距
  53. // 创建比特矩阵
  54. BitMatrix bitMatrix = new MultiFormatWriter().encode(contents,
  55. BarcodeFormat.QR_CODE, width, height, hints);
  56. return bitMatrix;
  57. }
  58. /**
  59. * 创建二维码,返回字节数组
  60. * @Date 2023/09/24 22:30
  61. * @Param contents 二维码里的内容
  62. * @Param imageFormat 图片后缀名
  63. * @Param width 二维码宽度
  64. * @Param height 二维码高度
  65. * @return byte[]
  66. */
  67. public static byte[] createQrCode(String contents, String imageFormat, int width, int height) throws WriterException, IOException {
  68. if (StrUtil.isBlank(imageFormat)) {
  69. imageFormat = DEFAULT_FORMAT_NAME;
  70. }
  71. BitMatrix bitMatrix = createBitMatrix(contents, width, height);
  72. ByteArrayOutputStream os = new ByteArrayOutputStream();
  73. MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, os);
  74. return os.toByteArray();
  75. }
  76. /**
  77. * 创建二维码,返回base64字符串
  78. * @Date 2023/09/24 22:30
  79. * @Param contents 二维码里的内容
  80. * @Param imageFormat 图片后缀名
  81. * @Param width 二维码宽度
  82. * @Param height 二维码高度
  83. * @return byte[]
  84. */
  85. public static String createQrCodeBase64(String contents, String imageFormat, int width, int height) throws WriterException, IOException {
  86. byte[] bytes = createQrCode(contents, imageFormat, width, height);
  87. return Base64.encode(bytes);
  88. }
  89. /**
  90. * 解码二维码
  91. * @Date 2023/09/24 22:32
  92. * @Param [image]
  93. * @return java.lang.String
  94. */
  95. public static String decodeQrCode(BufferedImage image) throws Exception {
  96. if (image == null) return StrUtil.EMPTY;
  97. BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
  98. BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
  99. Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
  100. hints.put(DecodeHintType.CHARACTER_SET, DEFAULT_CHAR_SET);
  101. Result result = new MultiFormatReader().decode(bitmap, hints);
  102. return result.getText();
  103. }
  104. /**
  105. * 转换为BufferedImage
  106. * @Date 2023/09/24 22:32
  107. * @Param [bitMatrix]
  108. * @return java.awt.image.BufferedImage
  109. */
  110. public static BufferedImage toBufferedImage(BitMatrix bitMatrix) throws IOException, WriterException {
  111. MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
  112. BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, matrixToImageConfig);
  113. return bufferedImage;
  114. }
  115. /**
  116. * 给二维码添加logo
  117. * @Date 2023/09/24 22:33
  118. * @Param [bufferedImage, logoFile]
  119. * @return java.awt.image.BufferedImage
  120. */
  121. public static BufferedImage addQrCodeLogo(BufferedImage bufferedImage, File logoFile) throws IOException {
  122. Graphics2D graphics = bufferedImage.createGraphics();
  123. int matrixWidth = bufferedImage.getWidth();
  124. int matrixHeigh = bufferedImage.getHeight();
  125. // 读取logo图片文件
  126. BufferedImage logo = ImageIO.read(logoFile);
  127. int logoWidth = logo.getWidth();
  128. int logoHeight = logo.getHeight();
  129. // 计算logo放置位置
  130. int x = bufferedImage.getWidth() / 5 * 2;
  131. int y = bufferedImage.getHeight() / 5 * 2;
  132. int width = matrixWidth / 5;
  133. int height = matrixHeigh / 5;
  134. // 开始绘制图片
  135. graphics.drawImage(logo, x, y, width, height, null);
  136. graphics.drawRoundRect(x, y, logoWidth, logoHeight, 15, 15);
  137. graphics.setStroke(new BasicStroke(5.0F, 1, 1));
  138. graphics.setColor(Color.white);
  139. graphics.drawRect(x, y, logoWidth, logoHeight);
  140. graphics.dispose();
  141. bufferedImage.flush();
  142. return bufferedImage;
  143. }
  144. /**
  145. * @version
  146. * @author: hxl
  147. * @Date: 2024/8/13 17:55
  148. * @Description: 返回二维码图片路径
  149. */
  150. public static String getQrCode(String orderNo, String url, String uploadPath) {
  151. BufferedImage bufferedImage = null;
  152. String fileName = orderNo + "_" + "_rwm.jpg"; // 修复文件名生成逻辑
  153. String saveFilePath = uploadPath + "/" + EXCEL_PATH + fileName;
  154. String resultPath = "/" + EXCEL_PATH + fileName; // 返回相对路径
  155. // 创建File对象
  156. File dir = new File(uploadPath + File.separator + EXCEL_PATH).getAbsoluteFile(); // 获取绝对路径
  157. // 判断目录是否存在
  158. if (!dir.exists() && !dir.mkdirs()) {
  159. throw new RuntimeException("目录不存在或创建失败,请重试!!");
  160. }
  161. try {
  162. bufferedImage = toBufferedImage(createBitMatrix(url, 300, 300));
  163. ImageIO.write(bufferedImage, "jpg", new File(saveFilePath)); // 修改为"jpg"以匹配文件名
  164. } catch (Exception e) {
  165. throw new RuntimeException("转为二维码报错,请重试!!", e);
  166. }
  167. return resultPath;
  168. }
  169. }