zxing生成二维码去除多余白边

白边问题
尺寸为100,100的时候,白边情况比较严重,左右上下都有8个像素的白边。
先考究一下为什么会产生白边,能不能去掉。

看一下encode方法。

@Override
  public BitMatrix encode(String contents,
                          BarcodeFormat format,
                          int width,
                          int height,
                          Map<EncodeHintType,?> hints) throws WriterException {

    if (contents.isEmpty()) {
      throw new IllegalArgumentException("Found empty contents");
    }

    if (format != BarcodeFormat.QR_CODE) {
      throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format);
    }

    if (width < 0 || height < 0) {
      throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' +
          height);
    }

    ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;
    int quietZone = QUIET_ZONE_SIZE;
    if (hints != null) {
      if (hints.containsKey(EncodeHintType.ERROR_CORRECTION)) {
        errorCorrectionLevel = ErrorCorrectionLevel.valueOf(hints.get(EncodeHintType.ERROR_CORRECTION).toString());
      }
      if (hints.containsKey(EncodeHintType.MARGIN)) {
        quietZone = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
      }
    }
	//没有涉及到宽高,仅仅和内容相关,那么我们的内容变成二维码就是这里
    QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints);
    //和宽高、以及刚刚生成的二维码相关,其中还有一个quietZone参数。
    return renderResult(code, width, height, quietZone);
  }
  // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
  // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
  // 假定初始输出的width为100,height为100
  private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) {
      ByteMatrix input = code.getMatrix();
      //计算出来的二维码大小,假设二维码最小大小为21
      int inputWidth = input.getWidth();
      int inputHeight = input.getHeight();
      //计算留白空间,设的0会在这里生效
      int qrWidth = inputWidth + (quietZone * 2);
      int qrHeight = inputHeight + (quietZone * 2);
      //计算二维码大小和我们提供给系统的尺寸比较,取最大值。
      int outputWidth = Math.max(width, qrWidth);
      int outputHeight = Math.max(height, qrHeight);
      //计算二维码与提供尺寸的倍率关系,用于放大缩小。如100/21=4
      int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
      // Padding includes both the quiet zone and the extra white pixels to accommodate the requested
      // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
      // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
      // handle all the padding from 100x100 (the actual QR) up to 200x160.
      //上述主要解释leftPadding和topPadding右边的计算赋值是什么意思。
      //计算左上分别空多少空间,(100-21*4)=8
      int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
      int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
      //取尺寸最大值的画布大小
      BitMatrix output = new BitMatrix(outputWidth, outputHeight);
      //从空出的第8个像素点开始,把二维码点1x1的结果放大至4x4写入画布中。
      for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
          // Write the contents of this row of the barcode
          for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
              if (input.get(inputX, inputY) == 1) {
                  output.setRegion(outputX, outputY, multiple, multiple);
              }
          }
      }

    return output;
  }

可以看到,在renderResult方法中,QRCodeWriter直接是将原本二维码像素值直接以整数倍率扩增,因为内容的大小导致对应尺寸和二维码像素值无法整除关系,为了适应用户输入的尺寸,所以才产生了白边。

所以去白边,本质上是将100x100变成84x84这种情况。

那么我们直接重新实现Writer,把其他代码基本照抄,然后把renderResult改写。

PS:为什么不是继承重写,是因为QRCodeWriter是一个被final修饰的类,不允许继承。

白边解决方案

 // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
  // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
  // 假定初始输出的width为100,height为100
  private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) {
      ByteMatrix input = code.getMatrix();
      int inputWidth = input.getWidth();
      int inputHeight = input.getHeight();
      int qrWidth = inputWidth + (quietZone * 2);
      int qrHeight = inputHeight + (quietZone * 2);
      int outputWidth = Math.max(width, qrWidth);
      int outputHeight = Math.max(height, qrHeight);
      int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
      
	  outputWidth = qrWidth * multiple;// 改动点
	  outputHeight = qrWidth * multiple;// 改动点
      
      // Padding includes both the quiet zone and the extra white pixels to accommodate the requested
      // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
      // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
      // handle all the padding from 100x100 (the actual QR) up to 200x160.
      int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
      int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
      leftPadding = 0 ;//改动点
      topPadding = 0 ;//改动点
      BitMatrix output = new BitMatrix(outputWidth, outputHeight);
      for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
          // Write the contents of this row of the barcode
          for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
              if (input.get(inputX, inputY) == 1) {
                  output.setRegion(outputX, outputY, multiple, multiple);
              }
          }
      }

    return output;
  }

如上,添加4行代码就可以完成去白边的功能需求。

启动代码

 public static void main(String[] args) {
        String myCodeText = "http://www.example.com";
        int size = 250;
        String filePath = "/Users/kiwi/dream/temp/QRCode.png";  // define your file path

        try {
            Hashtable<EncodeHintType, Object> hintMap = new Hashtable<>();
            hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
            hintMap.put(EncodeHintType.MARGIN, 0);  // Set the margin to remove the border
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix byteMatrix = qrCodeWriter.encode(myCodeText, BarcodeFormat.QR_CODE, size, size, hintMap);
            int CrunchifyWidth = byteMatrix.getWidth();
            BufferedImage image = new BufferedImage(CrunchifyWidth, CrunchifyWidth,
                    BufferedImage.TYPE_INT_RGB);
            image.createGraphics();

            for (int i = 0; i < CrunchifyWidth; i++) {
                for (int j = 0; j < CrunchifyWidth; j++) {
                    image.setRGB(i, j, (byteMatrix.get(i, j) ? java.awt.Color.BLACK.getRGB() : java.awt.Color.WHITE.getRGB()));
                }
            }

            // Save the image to a file
            File qrFile = new File(filePath);
            ImageIO.write(image, "PNG", qrFile);
        } catch (WriterException e) {
            // Handle the exception appropriately
            e.printStackTrace();
        } catch (IOException e) {
            // Handle the I/O exception
            e.printStackTrace();
        }
    }

结论
二维码的生成分为两部分:
第一部分是根据你的内容生成对应的二维码大小,如上图二维码的最小大小为21x21.
第二部分是根据用户输入的大小,如100x100就是先扩大成84x84,剩余16x16就变成4个方位的8x8白边。
因此白边是可以去除的,但是去除后白边的二维码因为是21*21,只能整数倍放大,做不到浮点值放大,因为最小单元像素点不能够再划分。
转载:https://www.cnblogs.com/vwymblog/p/11936216.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
zxing是一款非常优秀的开源库,可以帮助我们快速、方便地生成二维码。在使用zxing生成二维码时,我们需要先准备好相关的依赖和jar包,并使用QRCodeWriter类来生成普通的二维码。具体的生成过程如下: 1. 首先,我们需要下载zxing的jar包,并将其导入到项目中。 2. 在生成二维码的代码中,我们需要创建一个QRCodeWriter对象,用于生成二维码。然后,我们需要准备一些参数,如二维码的内容、宽度、高度等。这些参数会被传递给QRCodeWriter对象的encode方法。 3. 在生成二维码之前,我们可以设置一些可选的参数,如编码类型、字符集等。可以使用Hashtable对象来存储这些参数。 4. 调用QRCodeWriter对象的encode方法,传入参数,即可生成一个BitMatrix对象,它表示了一个二维码的矩阵。 5. 最后,我们可以将BitMatrix对象转换为图片,并保存到指定的文件路径中。 以上就是使用zxing生成二维码的基本步骤。如果需要生成带有Logo的二维码,我们可以使用MatrixToImageConfig类来实现。无论是生成普通的二维码还是带有Logo的二维码,zxing都是一个非常实用的工具。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [使用zxing生成二维码](https://blog.csdn.net/qinshengfei/article/details/131142998)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [二维码的知识 看这一篇就够了 使用zxing进行二维码的生成](https://blog.csdn.net/q15976405716/article/details/107402967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值