ZXing生成的二维码为什么会有白边,如何去除。 您所在的位置:网站首页 ps图片白边去掉 ZXing生成的二维码为什么会有白边,如何去除。

ZXing生成的二维码为什么会有白边,如何去除。

2023-07-24 08:41| 来源: 网络整理| 查看: 265

别人的代码

先放一下一份抄到的代码,一般的ZXing都是差不多这样写的

/** * @param args */ public static void main(String[] args) { try { String content = "{\"server\":4407}"; Integer width = 100; Integer height = 100; Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.MARGIN, 0); QRCodeWriter writer = new QRCodeWriter(); BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints); MatrixToImageWriter.writeToStream(bitMatrix, "jpg", new FileOutputStream("你好.jpg")); } catch (Exception e) { e.printStackTrace(); } }

结果图如下

白边问题

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

看一下encode方法。

@Override public BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Map 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) { try { String content = "{\"server\":4407}"; Integer width = 100; Integer height = 100; Map hints = new HashMap(); hints.put(EncodeHintType.CHARACTER_SET, "utf-8"); hints.put(EncodeHintType.MARGIN, 0); QCCodeWriterSelf writer = new QCCodeWriterSelf();//复制QCCodeWriter实现的类,仅仅添加了上述说明的4行代码 BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints); MatrixToImageWriter.writeToStream(bitMatrix, "jpg", new FileOutputStream("你好.jpg")); } catch (Exception e) { e.printStackTrace(); } }

文件图片结果如下所示

结论

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



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有