当前位置:   article > 正文

java 生成二维码、可带LOGO、可去白边

java qrcodewriter生成二维码不留白边
 

1.准备工作

  所需jar包:

JDK 1.6:

  commons-codec-1.11.jar

  core-2.2.jar

  javase-2.2.jar

JDK 1.7:

  commons-codec-1.11.jar

  core-3.2.1.jar

  javase-3.2.1.jar

  1. import java.awt.AlphaComposite;
  2. import java.awt.Graphics2D;
  3. import java.awt.image.BufferedImage;
  4. import java.io.ByteArrayOutputStream;
  5. import java.io.File;
  6. import java.io.OutputStream;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9. import javax.imageio.ImageIO;
  10. import org.apache.commons.codec.binary.Base64OutputStream;
  11. import com.google.zxing.BarcodeFormat;
  12. import com.google.zxing.EncodeHintType;
  13. import com.google.zxing.MultiFormatWriter;
  14. import com.google.zxing.client.j2se.MatrixToImageWriter;
  15. import com.google.zxing.common.BitMatrix;
  16. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
  17. /**
  18. * 维码处理工具类
  19. * @explain
  20. * @author Marydon
  21. * @creationTime 2018年11月23日下午3:16:55
  22. * @version 2.0
  23. * @since 1.0
  24. * @email marydon20170307@163.com
  25. */
  26. public class QRcodeUtils {
  27.    // base64编码集
  28. public static final String CHARSET = "UTF-8";
  29. // 二维码高度
  30. public static final int HEIGHT = 150;
  31. // 二维码宽度
  32. public static final int WIDTH = 150;
  33. // 二维码外边距
  34. public static final int MARGIN = 0;
  35. // 二维码图片格式
  36. private static final String FORMAT = "jpg";
  37. }  

2.生成二维码

  1. /**
  2. * 生成二维码
  3. * @explain
  4. * @param data 字符串(二维码实际内容)
  5. * @return
  6. */
  7. public static BufferedImage createQRCode(String data) {
  8. return createQRCode(data, WIDTH, HEIGHT, MARGIN);
  9. }
  10. /**
  11. * 生成二维码
  12. * @explain
  13. * @param data 字符串(二维码实际内容)
  14. * @param width 宽
  15. * @param height 高
  16. * @param margin 外边距,单位:像素,只能为整数,否则:报错
  17. * @return BufferedImage
  18. */
  19. public static BufferedImage createQRCode(String data, int width, int height, int margin) {
  20. BitMatrix matrix;
  21. try {
  22. // 设置QR二维码参数
  23. Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(2);
  24. // 纠错级别(H为最高级别)
  25. // L级:约可纠错7%的数据码字
  26. // M级:约可纠错15%的数据码字
  27. // Q级:约可纠错25%的数据码字
  28. // H级:约可纠错30%的数据码字
  29. hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
  30. // 字符集
  31. hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
  32. // 边框,(num * 10)
  33. hints.put(EncodeHintType.MARGIN, 0);// num
  34. // 编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
  35. matrix = new MultiFormatWriter().encode(data, BarcodeFormat.QR_CODE,
  36. width, height, hints);
  37. } catch (Exception e) {
  38. throw new RuntimeException(e.getMessage(), e);
  39. }
  40. return MatrixToImageWriter.toBufferedImage(matrix);
  41. }  

  说明:

  网上说,EncodeHintType.MARGIN的取值区间为[0,4],但是经过实际测试,当把它的值设为负整数、正整数的时候都不会报错,但不是能是小数;

  去白边,将EncodeHintType.MARGIN的值设为0的方法,根本无效,因为源码中并没有通过这个参数来设置白边的宽度;

  大致过程:先根据内容生成二维码,然后根据指定的宽高,对原来的二维码进行放大或缩小,白色边框的宽度=要求的宽高-放大或缩小后的二维码的宽高。

  com\google\zxing\qrcode\QRCodeWriter.class源码解读

  1. private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone)
  2. {
  3. ByteMatrix input = code.getMatrix();
  4. if (input == null)
  5. throw new IllegalStateException();
  6. int inputWidth = input.getWidth();
  7. int inputHeight = input.getHeight();
  8. int qrWidth = inputWidth + quietZone * 2;
  9. int qrHeight = inputHeight + quietZone * 2;
  10. int outputWidth = Math.max(width, qrWidth);
  11. int outputHeight = Math.max(height, qrHeight);
  12. int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
  13. // 有白色边框的罪魁祸首:leftPadding和topPadding
  14. int leftPadding = (outputWidth - inputWidth * multiple) / 2;
  15. int topPadding = (outputHeight - inputHeight * multiple) / 2;
  16. BitMatrix output = new BitMatrix(outputWidth, outputHeight);
  17. int inputY = 0; for (int outputY = topPadding; inputY < inputHeight; )
  18. {
  19. int inputX = 0; for (int outputX = leftPadding; inputX < inputWidth; ) {
  20. if (input.get(inputX, inputY) == 1)
  21. output.setRegion(outputX, outputY, multiple, multiple);
  22. ++inputX; outputX += multiple;
  23. }
  24. ++inputY; outputY += multiple;
  25. }
  26. return output;
  27. }  

3.去白边

  在createQRCode()方法中添加如下代码:

  1. // 裁减白边(强制减掉白边)
  2. if (margin == 0) {
  3. bitMatrix = deleteWhite(bitMatrix);
  4. }

  具体实现方法:

  1. /**
  2. * 强制将白边去掉
  3. * @explain
  4. * 虽然生成二维码时,已经将margin的值设为了0,但是在实际生成二维码时有时候还是会生成白色的边框,边框的宽度为10px;
  5. * 白边的生成还与设定的二维码的宽、高及二维码内容的多少(内容越多,生成的二维码越密集)有关;
  6. * 因为是在生成二维码之后,才将白边裁掉,所以裁剪后的二维码(实际二维码的宽、高)肯定不是你想要的尺寸,只能自己一点点试喽!
  7. * @param matrix
  8. * @return 裁剪后的二维码(实际二维码的大小)
  9. */
  10. private static BitMatrix deleteWhite(BitMatrix matrix) {
  11. int[] rec = matrix.getEnclosingRectangle();
  12. int resWidth = rec[2] + 1;
  13. int resHeight = rec[3] + 1;
  14. BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
  15. resMatrix.clear();
  16. for (int i = 0; i < resWidth; i++) {
  17. for (int j = 0; j < resHeight; j++) {
  18. if (matrix.get(i + rec[0], j + rec[1]))
  19. resMatrix.set(i, j);
  20. }
  21. }
  22. int width = resMatrix.getWidth();
  23. int height = resMatrix.getHeight();
  24. BufferedImage image = new BufferedImage(width, height,
  25. BufferedImage.TYPE_INT_RGB);
  26. for (int x = 0; x < width; x++) {
  27. for (int y = 0; y < height; y++) {
  28. image.setRGB(x, y, resMatrix.get(x, y) ? 0 : 255);// 0-黑色;255-白色
  29. }
  30. }
  31. return resMatrix;
  32. }

  说明:这种方法只能去除普通的二维码的白边,不能去除带LOGO的二维码的白边。

4.生成带logo的二维码

  1. /**
  2. * 生成带logo的二维码
  3. * @explain 宽、高、外边距使用定义好的值
  4. * @param data 字符串(二维码实际内容)
  5. * @param logoFile logo图片文件对象
  6. * @return BufferedImage
  7. */
  8. public static BufferedImage createQRCodeWithLogo(String data, File logoFile) {
  9. return createQRCodeWithLogo(data, WIDTH, HEIGHT, MARGIN, logoFile);
  10. }
  11. /**
  12. * 生成带logo的二维码
  13. * @explain 自定义二维码的宽和高
  14. * @param data 字符串(二维码实际内容)
  15. * @param width 宽
  16. * @param height 高
  17. * @param logoFile logo图片文件对象
  18. * @return BufferedImage
  19. * @return
  20. */
  21. public static BufferedImage createQRCodeWithLogo(String data, int width, int height, int margin, File logoFile) {
  22. BufferedImage combined = null;
  23. try {
  24. BufferedImage qrcode = createQRCode(data, width, height, margin);
  25. BufferedImage logo = ImageIO.read(logoFile);
  26. int deltaHeight = height - logo.getHeight();
  27. int deltaWidth = width - logo.getWidth();
  28. combined = new BufferedImage(height, width, BufferedImage.TYPE_INT_ARGB);
  29. Graphics2D g = (Graphics2D) combined.getGraphics();
  30. g.drawImage(qrcode, 0, 0, null);
  31. g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f));
  32. g.drawImage(logo, (int) Math.round(deltaWidth / 2), (int) Math.round(deltaHeight / 2), null);
  33. } catch (Exception e) {
  34. throw new RuntimeException(e.getMessage(), e);
  35. }
  36. return combined;
  37. }  

5.以什么样的方式返回二维码

  1. /**
  2. * 将二维码信息写入文件中
  3. * @explain
  4. * @param image
  5. * @param file 用于存储二维码的文件对象
  6. */
  7. public static void writeToFile(BufferedImage image, File file) {
  8. try {
  9. ImageIO.write(image, FORMAT, file);
  10. } catch (Exception e) {
  11. throw new RuntimeException(e.getMessage(), e);
  12. }
  13. }
  14. /**
  15. * 将二维码信息写入流中
  16. * @explain
  17. * @param image
  18. * @param 文件stream
  19. */
  20. public static void writeToStream(BufferedImage image, OutputStream stream) {
  21. try {
  22. ImageIO.write(image, FORMAT, stream);
  23. } catch (Exception e) {
  24. throw new RuntimeException(e.getMessage(), e);
  25. }
  26. }
  27. /**
  28. * 获取base64格式的二维码
  29. * @explain 图片类型:jpg
  30. * 展示:<img src="https://img-blog.csdnimg.cn/2022010705272447267.jpeg"/>
  31. * @param image
  32. * @return base64
  33. */
  34. public static String writeToString(BufferedImage image) {
  35. String base64Str;
  36. try {
  37. ByteArrayOutputStream bos = new ByteArrayOutputStream();
  38. OutputStream os = new Base64OutputStream(bos);
  39. writeToStream(image, os);
  40. // 按指定字符集进行转换并去除换行符
  41. base64Str = bos.toString(CHARSET).replace("\r\n", "");
  42. } catch (Exception e) {
  43. throw new RuntimeException(e.getMessage(), e);
  44. }
  45. return base64Str;
  46. }  

6.base64生成图片

  1. /**
  2. * 将base64转成图片
  3. * @explain
  4. * @param base64 base64格式图片
  5. * @param file 用于存储二维码的文件对象
  6. */
  7. public static void base64ToImage(String base64, File file) {
  8. FileOutputStream os;
  9. try {
  10. Base64 d = new Base64();
  11. byte[] bs = d.decode(base64);
  12. os = new FileOutputStream(file.getAbsolutePath());
  13. os.write(bs);
  14. os.close();
  15. } catch (Exception e) {
  16. throw new RuntimeException(e.getMessage(), e);
  17. }
  18. }

7.测试

  见文末推荐

2018/11/29

  添加二维码边框参数设置;

  代码优化。

2018/11/30

  添加去除白边功能。

 

 
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/604396
推荐阅读
相关标签
  

闽ICP备14008679号