【问题标题】:Reduce border width on QR Codes generated by ZXing?减少 ZXing 生成的二维码的边框宽度?
【发布时间】:2012-04-13 14:30:01
【问题描述】:

我使用com.google.zxing.qrcode.QRCodeWriter 对数据进行编码,使用com.google.zxing.client.j2se.MatrixToImageWriter 生成二维码图像。在 400x400 图像上,代码周围有大约 52 像素宽的边框。我希望这个边框更窄,可能是 15 像素,但我在 API 中看不到任何这样做的东西。我在文档中遗漏了什么吗?还是我需要自己处理图像?

作为参考,这里是使用 ZXing 库生成的 400x400 二维码示例:

【问题讨论】:

    标签: zxing


    【解决方案1】:

    QR 规范需要四个模块的静区,这就是 zxing creates。 (参见QRCodeWriter.renderResult 中的QUIET_ZONE_SIZE。)

    ZXing 的最新版本允许您通过使用 EncodeHintType.MARGIN 键提供一个 int 值来设置静区的大小(基本上是 QR 码的固有填充)。只需将其包含在您提供给Writerencode(...) 方法的提示Map 中,例如:

    Map<EncodeHintType, Object> hints = new EnumMap<EncodeHintType, Object>(EncodeHintType.class);
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    hints.put(EncodeHintType.MARGIN, 2); /* default = 4 */
    

    如果更改此设置,可能会降低解码成功率。

    【讨论】:

    • 我想我会处理它。谢谢。
    • 我可以根据经验确认,根本没有静区的代码通常不会扫描。
    • 对。我不能代表其他解码器,但 zxing 使用启发式方法来检测假设有一个安静区域的二维码。启发式并不假设规范中所说的安静区是四个模块宽,但如果它不存在或太窄,zxing 解码成功率很可能会降低,很可能会显着降低。
    • 你能更新死链接,让它指向“安静区域”上的工作链接吗?
    • 修复了链接,但正如后续编辑所说,您现在可以使用选项进行设置。 (不过,该选项上的文档看起来有点不精确。静区大小以模块为单位。MARGIN 选项上的 cmets 说它以像素为单位,但查看代码,它似乎正在设置静区大小QR 码。我没有进一步验证,但我怀疑 MARGIN 在 QR 码模块中。
    【解决方案2】:

    即使通过将EncodeHintType.MARGIN 设置为0,将二维码“点”矩阵转换为像素数据的算法也可以生成较小的边距(该算法强制每个点的像素数恒定,因此边距像素大小为像素大小除以二维码点大小的整数除法的余数。

    但是您可以完全绕过这种“点到像素”的生成:您可以通过调用公共com.google.zxing.qrcode.encoder.Encoder 类直接计算二维码点阵,并自己生成像素图像。代码如下:

    // Step 1 - generate the QRCode dot array
    Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>(1);
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    QRCode qrCode = Encoder.encode(what, ErrorCorrectionLevel.L, hints);
    
    // Step 2 - create a BufferedImage out of this array
    int width = qrCode.getMatrix().getWidth();
    int height = qrCode.getMatrix().getHeight();
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    int[] rgbArray = new int[width * height];
    int i = 0;
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        rgbArray[i] = qrCode.getMatrix().get(x, y) > 0 ? 0xFFFFFF : 0x000000;
        i++;
    } }
    image.setRGB(0, 0, width, height, rgbArray, 0, width);
    

    BufferedImage 到 PNG 数据的转换留给读者作为练习。您还可以通过设置每个点的固定像素数来缩放图像。

    这种方式通常更优化,生成的图像尺寸尽可能小。如果您依赖客户端来缩放图像(无模糊),则每个点不需要超过 1 个像素。

    【讨论】:

    • 请注意,颜色似乎颠倒了,我不得不使用if (matrix.get(x, y) == 0) { rgbArray[i] = 0xFFFFFF; } i++; 来获得类似于 Zxing 的输出。
    • @RC。感谢您的提示,我没有注意到这一点。但是你确定吗?我使用此代码获得的 QRCode 似乎匹配。
    • 另一种方法是检索边距的大小(例如,总大小以每个点的像素数为模)并使用 ImageIO 变换缩放图像。
    【解决方案3】:
        HashMap hintMap = new HashMap();
        hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
        hintMap.put(EncodeHintType.MARGIN, -1);
    

    没有边距

    更新

    添加依赖项(来自 cmets)

    <dependency>
        <groupId>com.google.zxing</groupId> 
        <artifactId>core</artifactId> 
        <version>3.2.0</version>
        <type>jar</type> 
    </dependency> 
    <dependency> 
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId> 
        <version>3.2.0</version> 
    </dependency>
    

    【讨论】:

    • 这会引发异常(
    • com.google.zxingcore3.2.0jarcom.google.zxingjavase3.2.0 添加依赖项
    • 这就是我的解决方案!谢谢。
    • 我使用了这个解决方案。但是,我收到了Left and top must be nonnegative 错误。需要注意的是,仅针对某些有效负载引发了异常。 99%的时间,它成功了。但是对于那 1%,发生了错误。为什么?
    • 当我将它设置为0而不是-1时,它成功了
    【解决方案4】:

    swift 中,您可以:

    let hints = ZXEncodeHints()
    hints!.margin = NSNumber(int: 0)
    
    let result = try writer.encode(code, format: format, width: Int32(size.width), height: Int32(size.height), hints: hints)
    let cgImage = ZXImage(matrix: result, onColor: UIColor.blackColor().CGColor, offColor: UIColor.clearColor().CGColor).cgimage
    let QRImage = UIImage(CGImage: cgImage)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      相关资源
      最近更新 更多