本帖最后由 三木猿 于 2021-12-27 10:42 编辑
最近做的一个批量生成二维码的工具用到了二维码生成,本以为会很简单,结果发现,全是坑呀
坑一、生成的二维码有白边,ZXING提供的设置白边大小的方法有bug。。
这个着实坑人,提供了设置白边的方法,结果用了白边反而变大了,并且不受控制了
从别的地方截取出来的,大概就长这样,这玩意能用???简直奇葩了
ZXING提供的办法(有坑)
[Java] 纯文本查看 复制代码 Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 0);//这里实际上设置的就是白边宽度,但是在源码里不是按照你想的那样设置几就是几,计算白边的宽度时用到了二维码宽度和高度当参数,这就造成想设置0px,结果出现10px白边的情况
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, intEwmWidth, intEwmHeight,
hints);
源码里计算白边宽度的方法,我给他封装出来了,可以直接用
[Java] 纯文本查看 复制代码 /**
* 获取白边宽度
* [url=home.php?mod=space&uid=952169]@Param[/url] code
* @param width
* @param height
* @param quietZone
* @return
*/
public Integer getPadding(QRCode code, int width, int height, int quietZone) {
ByteMatrix input = code.getMatrix();
int inputWidth = input.getWidth();
int inputHeight = input.getHeight();
int qrWidth = inputWidth + (quietZone << 1);
int qrHeight = inputHeight + (quietZone << 1);
int outputWidth = Math.max(width, qrWidth);
int outputHeight = Math.max(height, qrHeight);
int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
int leftPadding = (outputWidth - inputWidth * multiple) / 2;
return leftPadding;
}
其中QRCode的生成方式是
[Java] 纯文本查看 复制代码 ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.valueOf(hints.get(EncodeHintType.ERROR_CORRECTION).toString());
//contents这个就是二维码的文本,一般是url,自己设置的,hints上文出现过,可以往上滑看一下
Encoder.encode(contents, errorCorrectionLevel, hints)
解决办法:百度上提供了一种办法,的确是有用的
这个方法种的margin单位是像素(px)(手动量过,绝对是像素)
[Java] 纯文本查看 复制代码 //删除白边
private static BitMatrix updateBit(BitMatrix matrix, int margin) {
int tempM = margin * 2;
int[] rec = matrix.getEnclosingRectangle(); // 获取二维码图案的属性 集合中前两个是白边的宽和高,后两个是二维码去白边之后的宽度和高度
int resWidth = rec[2] + tempM;
int resHeight = rec[3] + tempM;
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); // 按照自定义边框生成新的BitMatrix
resMatrix.clear();
for (int i = margin; i < resWidth - margin; i++) { // 循环,将二维码图案绘制到新的bitMatrix中
for (int j = margin; j < resHeight - margin; j++) {
if (matrix.get(i - margin + rec[0], j - margin + rec[1])) {
resMatrix.set(i, j);
}
}
}
return resMatrix;
}
坑二、去白边后二维码缩小
这个方法的坑
这个方法实际上就是在原来二维码的数据上进行截取白边的操作matrix.get(i - margin + rec[0], j - margin + rec[1])
这个意思就是获取每一个像素的x和y的坐标的时候从自己设置的像素位置开始。
所以坑就来了,我生成二维码的时候设置的100x100大小,结果白边是去了,二维码变小了,这哪能行,并且原来白边越大,缩小的越多
这个坑的解决办法
之前研究了几个小时,几乎就改源码重新写一个生成逻辑了,然后突然就茅塞顿开
他缩小了,我给他放大不就完了。。
BitMatrix 是需要转成BufferedImage 输出的,BufferedImage 就是个存图片的,既然是图片就肯定能放大,并且因为去掉的白边后的大小和去白边之前的大小差距并不大,既然如此,那我为啥不直接放大二维码呢。。
先转BufferedImage
[Java] 纯文本查看 复制代码 int intEwmWidth1 = bitMatrix.getWidth();
int intEwmHeight1 = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(intEwmWidth1, intEwmHeight1, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < intEwmWidth1; x++) {
for (int y = 0; y < intEwmHeight1; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
然后放大,设置二维码大小
[Java] 纯文本查看 复制代码 private static BufferedImage zoomInImage(BufferedImage originalImage, int maxWidth, int maxHeight) {
BufferedImage newImage = new BufferedImage(maxWidth, maxHeight, originalImage.getType());
Graphics g = newImage.getGraphics();
g.drawImage(originalImage, 0, 0, maxWidth, maxHeight, null);
g.dispose();
return newImage;
}
至此二维码的算是填了吧,至少比原来强,但是最好的方式是改源码,我提供的方法会导致白边大小不是设置的4,而是等比例放大的(当然差距其实不大)
附一张我生成的二维码(别扫,扫了就知道我忙的什么项目了)
附带的完整代码(1cb不过分吧,或者你也可以看我的文章,里面代码也都有)
QrCodeUtils.zip
(2.28 KB, 下载次数: 21)
|