分享

更详细的二维码生成和解析

 勃士159131 2022-10-29 发布于广东

1,依赖

  1. <dependency>
  2. <groupId>com.google.zxing</groupId>
  3. <artifactId>core</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

2,帮助类

  1. package cn.hyt.hyt_zhdj_cs.utils;
  2. import java.awt.Graphics2D;
  3. import java.awt.geom.AffineTransform;
  4. import java.awt.image.BufferedImage;
  5. import com.google.zxing.LuminanceSource;
  6. public class BufferedImageLuminanceSource extends LuminanceSource {
  7. private final BufferedImage image;
  8. private final int left;
  9. private final int top;
  10. public BufferedImageLuminanceSource(BufferedImage image) {
  11. this(image, 0, 0, image.getWidth(), image.getHeight());
  12. }
  13. public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {
  14. super(width, height);
  15. int sourceWidth = image.getWidth();
  16. int sourceHeight = image.getHeight();
  17. if (left + width > sourceWidth || top + height > sourceHeight) {
  18. throw new IllegalArgumentException('Crop rectangle does not fit within image data.');
  19. }
  20. for (int y = top; y < top + height; y++) {
  21. for (int x = left; x < left + width; x++) {
  22. if ((image.getRGB(x, y) & 0xFF000000) == 0) {
  23. image.setRGB(x, y, 0xFFFFFFFF); // = white
  24. }
  25. }
  26. }
  27. this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
  28. this.image.getGraphics().drawImage(image, 0, 0, null);
  29. this.left = left;
  30. this.top = top;
  31. }
  32. public byte[] getRow(int y, byte[] row) {
  33. if (y < 0 || y >= getHeight()) {
  34. throw new IllegalArgumentException('Requested row is outside the image: ' + y);
  35. }
  36. int width = getWidth();
  37. if (row == null || row.length < width) {
  38. row = new byte[width];
  39. }
  40. image.getRaster().getDataElements(left, top + y, width, 1, row);
  41. return row;
  42. }
  43. public byte[] getMatrix() {
  44. int width = getWidth();
  45. int height = getHeight();
  46. int area = width * height;
  47. byte[] matrix = new byte[area];
  48. image.getRaster().getDataElements(left, top, width, height, matrix);
  49. return matrix;
  50. }
  51. public boolean isCropSupported() {
  52. return true;
  53. }
  54. public LuminanceSource crop(int left, int top, int width, int height) {
  55. return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
  56. }
  57. public boolean isRotateSupported() {
  58. return true;
  59. }
  60. public LuminanceSource rotateCounterClockwise() {
  61. int sourceWidth = image.getWidth();
  62. int sourceHeight = image.getHeight();
  63. AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
  64. BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
  65. Graphics2D g = rotatedImage.createGraphics();
  66. g.drawImage(image, transform, null);
  67. g.dispose();
  68. int width = getWidth();
  69. return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
  70. }
  71. }

3,工具类

  1. package cn.hyt.hyt_zhdj_cs.utils;
  2. import java.awt.BasicStroke;
  3. import java.awt.Graphics;
  4. import java.awt.Graphics2D;
  5. import java.awt.Image;
  6. import java.awt.Shape;
  7. import java.awt.geom.RoundRectangle2D;
  8. import java.awt.image.BufferedImage;
  9. import java.io.File;
  10. import java.io.OutputStream;
  11. import java.util.Hashtable;
  12. import javax.imageio.ImageIO;
  13. import com.google.zxing.BarcodeFormat;
  14. import com.google.zxing.BinaryBitmap;
  15. import com.google.zxing.DecodeHintType;
  16. import com.google.zxing.EncodeHintType;
  17. import com.google.zxing.MultiFormatReader;
  18. import com.google.zxing.MultiFormatWriter;
  19. import com.google.zxing.Result;
  20. import com.google.zxing.common.BitMatrix;
  21. import com.google.zxing.common.HybridBinarizer;
  22. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
  23. public class QRCodeUtil {
  24. private static final String CHARSET = 'utf-8';
  25. private static final String FORMAT_NAME = 'JPG';
  26. // 二维码尺寸
  27. private static final int QRCODE_SIZE = 300;
  28. // LOGO宽度
  29. private static final int WIDTH = 60;
  30. // LOGO高度
  31. private static final int HEIGHT = 60;
  32. private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
  33. Hashtable hints = new Hashtable();
  34. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
  35. hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
  36. hints.put(EncodeHintType.MARGIN, 1);
  37. BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
  38. hints);
  39. int width = bitMatrix.getWidth();
  40. int height = bitMatrix.getHeight();
  41. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  42. for (int x = 0; x < width; x++) {
  43. for (int y = 0; y < height; y++) {
  44. image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
  45. }
  46. }
  47. if (imgPath == null || ''.equals(imgPath)) {
  48. return image;
  49. }
  50. // 插入图片
  51. QRCodeUtil.insertImage(image, imgPath, needCompress);
  52. return image;
  53. }
  54. private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
  55. File file = new File(imgPath);
  56. if (!file.exists()) {
  57. System.err.println('' + imgPath + ' 该文件不存在!');
  58. return;
  59. }
  60. Image src = ImageIO.read(new File(imgPath));
  61. int width = src.getWidth(null);
  62. int height = src.getHeight(null);
  63. if (needCompress) { // 压缩LOGO
  64. if (width > WIDTH) {
  65. width = WIDTH;
  66. }
  67. if (height > HEIGHT) {
  68. height = HEIGHT;
  69. }
  70. Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
  71. BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
  72. Graphics g = tag.getGraphics();
  73. g.drawImage(image, 0, 0, null); // 绘制缩小后的图
  74. g.dispose();
  75. src = image;
  76. }
  77. // 插入LOGO
  78. Graphics2D graph = source.createGraphics();
  79. int x = (QRCODE_SIZE - width) / 2;
  80. int y = (QRCODE_SIZE - height) / 2;
  81. graph.drawImage(src, x, y, width, height, null);
  82. Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
  83. graph.setStroke(new BasicStroke(3f));
  84. graph.draw(shape);
  85. graph.dispose();
  86. }
  87. public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
  88. BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
  89. mkdirs(destPath);
  90. // String file = new Random().nextInt(99999999)+'.jpg';
  91. // ImageIO.write(image, FORMAT_NAME, new File(destPath+'/'+file));
  92. ImageIO.write(image, FORMAT_NAME, new File(destPath));
  93. }
  94. public static BufferedImage encode(String content, String imgPath, boolean needCompress) throws Exception {
  95. BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
  96. return image;
  97. }
  98. public static void mkdirs(String destPath) {
  99. File file = new File(destPath);
  100. // 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
  101. if (!file.exists() && !file.isDirectory()) {
  102. file.mkdirs();
  103. }
  104. }
  105. public static void encode(String content, String imgPath, String destPath) throws Exception {
  106. QRCodeUtil.encode(content, imgPath, destPath, false);
  107. }
  108. // 被注释的方法
  109. /*
  110. * public static void encode(String content, String destPath, boolean
  111. * needCompress) throws Exception { QRCodeUtil.encode(content, null, destPath,
  112. * needCompress); }
  113. */
  114. public static void encode(String content, String destPath) throws Exception {
  115. QRCodeUtil.encode(content, null, destPath, false);
  116. }
  117. public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
  118. throws Exception {
  119. BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
  120. ImageIO.write(image, FORMAT_NAME, output);
  121. }
  122. public static void encode(String content, OutputStream output) throws Exception {
  123. QRCodeUtil.encode(content, null, output, false);
  124. }
  125. public static String decode(File file) throws Exception {
  126. BufferedImage image;
  127. image = ImageIO.read(file);
  128. if (image == null) {
  129. return null;
  130. }
  131. BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
  132. BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
  133. Result result;
  134. Hashtable hints = new Hashtable();
  135. hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
  136. result = new MultiFormatReader().decode(bitmap, hints);
  137. String resultStr = result.getText();
  138. return resultStr;
  139. }
  140. public static String decode(String path) throws Exception {
  141. return QRCodeUtil.decode(new File(path));
  142. }
  143. }

4,应用

  1. @ApiOperation(value = '二维码')
  2. @PostMapping('qrcode')
  3. public AppResponseJson qrcode() throws Exception {
  4. // 存放在二维码中的内容
  5. String text = '我是小铭';
  6. // 嵌入二维码的图片路径
  7. String imgPath = 'G:/qrCode/dog.jpg';
  8. // 生成的二维码的路径及名称
  9. String destPath = 'G:/qrCode/qrcode/jam.jpg';
  10. //生成二维码
  11. QRCodeUtil.encode(text, imgPath, destPath, true);
  12. // 解析二维码
  13. String str = QRCodeUtil.decode(destPath);
  14. // 打印出解析出的内容
  15. System.out.println(str);
  16. return AppResponseJson.successRequest('成功');
  17. }

生成二维码方法:

QRCodeUtil.encode(text, imgPath, destPath, true);

text:编码到二维码中的内容,这里是“我是小铭”

imgPath:要嵌入二维码的图片路径,如果不写或者为null则生成一个没有嵌入图片的纯净的二维码

destPath:生成的二维码的存放路径

true:表示将嵌入二维码的图片进行压缩,如果为“false”则表示不压缩。

解析二维码方法:

QRCodeUtil.decode(destPath);

destPath:将要解析的二维码的存放路径

该方法返回值为String类型,即返回解析出的文字或者数字等。

如果你想让别人扫描后跳转一个页面的话,直接在编码的方法里,将编码内容改为一个地址就可以了,这样别人扫描二维码后会自动跳转.二维码存的信息越多,二维码图片也就越复杂,容错率也就越低,识别率也越低,并且二维码能存的内容大小也是有限的(大概500个汉字左右)。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约