吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 1218|回复: 8
收起左侧

[Java] 用ZXING生成二维码的那些坑和去坑代码

[复制链接]
三木猿 发表于 2021-12-27 10:41
本帖最后由 三木猿 于 2021-12-27 10:42 编辑

最近做的一个批量生成二维码的工具用到了二维码生成,本以为会很简单,结果发现,全是坑呀
坑一、生成的二维码有白边,ZXING提供的设置白边大小的方法有bug。。
这个着实坑人,提供了设置白边的方法,结果用了白边反而变大了,并且不受控制了
从别的地方截取出来的,大概就长这样,这玩意能用???简直奇葩了
image.png
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,而是等比例放大的(当然差距其实不大)
附一张我生成的二维码(别扫,扫了就知道我忙的什么项目了
image.png


附带的完整代码(1cb不过分吧,或者你也可以看我的文章,里面代码也都有)
QrCodeUtils.zip (2.28 KB, 下载次数: 12)






免费评分

参与人数 2吾爱币 +1 热心值 +2 收起 理由
傲天越 + 1 热心回复!
xiaolong23330 + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

xiaolong23330 发表于 2021-12-27 10:58
谢谢分享个人经验
金冰 发表于 2021-12-27 11:13
xymoc 发表于 2021-12-27 11:17
denghuibq 发表于 2021-12-27 11:50
感谢分享~
MOEYU_VANILLA 发表于 2021-12-27 11:53
感谢分享!!
kenxy 发表于 2021-12-27 11:57
谢谢分享经验
thysut 发表于 2022-1-10 14:04
感谢分享
傲天越 发表于 2022-1-18 19:14
感谢楼主分享,学习了!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2022-5-18 17:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表