欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Zxing 生成二维码和条形码去掉白边

程序员文章站 2024-01-27 12:04:52
...

源码下载:

https://github.com/AndroidZmm123/ZxingApplication

需求:根据输入内容,生成条形码或者二维码。

我们大多数会选择Zxing。因为jar包较小。且使用简单。根据内容生成二维码的工具类也是一搜一大堆。上面的源码里面也提供了一个。但是我们仔细看了下。会发现。不管生成的是条形码还是二维码都会有一部分的白边。如图:

Zxing 生成二维码和条形码去掉白边

我们可以看到周围有白边。那我们怎么去掉呢。

我们先把zxing的源码下载下来。然后看下这个白边是如果产生的。

首先是二维码的。

            BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
                heightPix, hints);

这是根据我们输入的内容。产生一个矩阵。我们可以看到QRCodeWriter的encode()方法里面的最后两行:

   QRCode code = Encoder.encode(contents, errorCorrectionLevel, hints);
        return renderResult(code, width, height, quietZone);

第一句是将我们输入的内容转换成code.不涉及宽高。

第二句是将code转换成矩阵。加入白边的代码就在这里面。

private static BitMatrix renderResult(QRCode code, int width, int height, int quietZone) {
        ByteMatrix input = code.getMatrix();
        if (input == null) {
            throw new IllegalStateException();
        }
        int inputWidth = input.getWidth();
        int inputHeight = input.getHeight();

        //这里就是在我们给定的宽高的基础上。增加了大小。
        //int qrWidth = inputWidth + (quietZone * 2);
        //int qrHeight = inputHeight + (quietZone * 2);

        //修改--》去掉间距
        int qrWidth = inputWidth;
        int qrHeight = inputHeight;

        int outputWidth = Math.max(width, qrWidth);
        int outputHeight = Math.max(height, qrHeight);

        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.

        //计算白边的大小。
        //int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
        //int topPadding = (outputHeight - (inputHeight * multiple)) / 2;

        //修改--》去掉间距
        int leftPadding = 0;
        int 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;
    }

这样就二维码的白边就去掉了。

效果图:

Zxing 生成二维码和条形码去掉白边

再来看条形码的。条形码的修改稍微麻烦点。

条形码的解析类是:Code128Writer。进去同样可以找到encode()。调用的是父类的encode()。

 int sidesMargin = getDefaultMargin();
        if (hints != null && hints.containsKey(EncodeHintType.MARGIN)) {
            sidesMargin = Integer.parseInt(hints.get(EncodeHintType.MARGIN).toString());
        }

        boolean[] code = encode(contents);
        return renderResult(code, width, height, sidesMargin);

这里有个sideMargin..emmm。看着像是白边的大小的样子。我试着先把这个值修改为0.默认是10.修改以后。运行起来可以发现。还是有白边。看来这不是全部。看下renderResult()方法。

 /**
     * @return a byte array of horizontal pixels (0 = white, 1 = black)
     */
    private static BitMatrix renderResult(boolean[] code, int width, int height, int sidesMargin) {
        int inputWidth = code.length;
        // Add quiet zone on both sides.

        int fullWidth = inputWidth + sidesMargin;

        int outputWidth = Math.max(width, fullWidth);


        int outputHeight = Math.max(1, height);
        int multiple = outputWidth / fullWidth;
      
        Log.e("zmm", outputWidth + "renderResult-->" + inputWidth + "--->" + multiple);
        int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
        Log.e("zmm", "间距----------->" + leftPadding);
        BitMatrix output = new BitMatrix(outputWidth, outputHeight);
        for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX +=
            multiple) {
            if (code[inputX]) {
                output.setRegion(outputX, 0, multiple, outputHeight);
            }
        }
        return output;

    }

我们可以看到leftPadding。我试着把这个值修改为0.发现还是不行,有白边。

仔细看下。这个规则。我们的宽度是700px.我们刚刚已经把sideMargin修改成0了。所以

fullWidth=700;

inputWidth:是根据我们的内容根据128编码生成的一个数组的长度。我们输入1234567890:这里的inputWidth:90

multiple=700/90=7.77777;但是这里是int。所以multiple=7;这就产生了误差。multiple看成是竖线之间的增量。也就是,第一个竖线坐标是0,第二个竖线就应该在0+multiple的位置,以此类推。总共有90个竖线。那90*7<700.那还剩下的70.就只能平分当做左右的白边。

leftPadding=(outputWidth - (inputWidth * multiple)) / 2;也就是(700-90*7)/2=35.所以我们算出白边应该是35。

这样一下来我们就知道该怎么修改这个长度了。我们值修改leftPadding=0的话。那就会剩下70的空白。所以。不行。我们要做的事修改原始的图片大小。故修改成:

 /**
     * @return a byte array of horizontal pixels (0 = white, 1 = black)
     */
    private static BitMatrix renderResult(boolean[] code, int width, int height, int sidesMargin) {
        int inputWidth = code.length;
        // Add quiet zone on both sides.

        int fullWidth = inputWidth + sidesMargin;

        int outputWidth = Math.max(width, fullWidth);


        int outputHeight = Math.max(1, height);
        int multiple = outputWidth / fullWidth;
        //先判断是不是可以整除。如果可以整除。那leftPadding肯定为0,就不需要修改。
        // 如果不能整除。需要把原始的大小修改成outputWidth = multiple * fullWidth;这样以后。leftPadding也就为0了。
        if (outputHeight % fullWidth != 0) {
            outputWidth = multiple * fullWidth;
        }
        Log.e("zmm", outputWidth + "renderResult-->" + inputWidth + "--->" + multiple);
        int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
        Log.e("zmm", "间距----------->" + leftPadding);
        BitMatrix output = new BitMatrix(outputWidth, outputHeight);
        for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX +=
            multiple) {
            if (code[inputX]) {
                output.setRegion(outputX, 0, multiple, outputHeight);
            }
        }
        return output;

    }

这样以后。我们还需要在生成条形码那里把真实大小修改成我们改过以后的。也就是:

/**
     * 绘制条形码
     *
     * @param content       要生成条形码包含的内容
     * @param widthPix      条形码的宽度
     * @param heightPix     条形码的高度
     * @param isShowContent 否则显示条形码包含的内容
     * @return 返回生成条形的位图
     */
    public static Bitmap createBarcode(String content, int widthPix, int heightPix, boolean isShowContent) {
        if (TextUtils.isEmpty(content)) {
            return null;
        }
        //配置参数
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 容错级别 这里选择最高H级别
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        MultiFormatWriter writer = new MultiFormatWriter();

        try {
            // 图像数据转换,使用了矩阵转换 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
            BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.CODE_128, widthPix, heightPix, hints);

            //增加:把宽度修改我们修改过后的真实的宽度
            widthPix = bitMatrix.getWidth();
            // Log.e("zmm", "---------->" + widthPix + "--->" + height);
            int[] pixels = new int[widthPix * heightPix];
//             下面这里按照条形码的算法,逐个生成条形码的图片,
            // 两个for循环是图片横列扫描的结果
            for (int y = 0; y < heightPix; y++) {
                for (int x = 0; x < widthPix; x++) {
                    if (bitMatrix.get(x, y)) {
                        pixels[y * widthPix + x] = 0xff000000; // 黑色
                    } else {
                        pixels[y * widthPix + x] = 0xffffffff;// 白色
                    }
                }
            }
            Bitmap bitmap = Bitmap.createBitmap(widthPix, heightPix, Bitmap.Config.ARGB_8888);
            bitmap.setPixels(pixels, 0, widthPix, 0, 0, widthPix, heightPix);
            if (isShowContent) {
                bitmap = showContent(bitmap, content);
            }
            return bitmap;
        } catch (WriterException e) {
            e.printStackTrace();
        }

        return null;
    }

运行看下效果:

Zxing 生成二维码和条形码去掉白边

至此百边就去掉了。当然这样不好看。你也可以。自己来定一个固定的白边的宽度。我觉得还是不要去掉的比较好。因为。毕竟zxing这样设计肯定有一定的原因。

每日语录:

看到一个故事叫“刻舟求剑”,心里觉得这个人好傻,世上怎么会有这样的人,难道不知道剑在江*掉下了水,跑到江边是找不到的?然而长大后发现,在这条岁月的长河里,很多人在某个节点遗失的东西,之后一次又一次返回寻找,却不知道自己只是站在船边徘徊,江*已经回不去了。看到一个故事叫“掩耳盗铃”,心里想,这又是一个傻瓜,捂着耳朵偷东西骗的了谁?然而长大后发现,自己和同学一起逃课、一起抄作业、一起考试作弊,一起做许多明知道不应该做却克制不住自己的事情。没有被抓到就沾沾自喜,其实警告的铃声早已响起,只是自己捂着耳朵假装听不到。看到一个故事叫“朝三暮四”,心里偷笑,这群猴子怎么如此好骗,明明就是七个栗子,早晨三个晚上四个变成早晨四个晚上三个就一个个被哄得服服帖帖。然而长大后发现,女孩儿被渣男伤害,对面一个道歉就还是原谅了他;商家使个小小的心眼儿,几块钱红包就引得全国人趋之若鹜……我们不比猴子聪明多少。看到一个故事叫“削足适履”,心里哀叹,怎么会有这样的蠢人,居然会蠢到砍自己的脚去适应鞋子,换一双鞋子就那么难吗?然而长大后发现,明明知道自己的权益被损害,明明知道这样的环境和体系并不科学,然而在这其中的每个人却都默不作声,甘心忍受。看到一个故事叫“邯郸学步”,心里崩溃,为什么成语故事里的人一个比一个傻?别人走路姿势好看就去模仿,到了最后居然忘了自己怎么走路?然而长大后却发现,这个世界的确被一股股潮流所带领,今天“假装生活”,明天“佛系青年”;今天都在比拼“跳一跳”,明天都在晒“养青蛙”。现在谁能想象,自己扔掉手机生活的样子?原来,成语中那些傻事儿可能没有人会去干,但是,成语里那些傻瓜,却是真实地存在着    ---------------------------------来自知乎(作者:雾雨之灵)

单曲循环《曾经的你》第一次找工作那段时间天天听。。因为太迷茫了。太惶恐了。听着这首歌。沿着一条路。一直走。一直走。想把以后的路想明白,想清楚。其实。。根本毫无用处。路都是走着走着就明白了。愿看到这段话的你。可以少些苦恼。少些惶恐。加油!!!

 

上一篇: MySQL连接Java

下一篇: java连接mysql