zxing 设置条码两边空白 (EncodeHintType.MARGIN) 无效的分析

本贴最后更新于 2687 天前,其中的信息可能已经时移世改

zxing 设置条码两边空白(EncodeHintType.MARGIN)无效的分析,有需要的朋友可以参考下。

最新项目需要使用到 zxing 生成条码,条码格式为 CODE128,CODE128 的规则可参考:点击打开链接

当调用
MultiFormatWriter().encode(str,BarcodeFormat.CODE_128, mwidth, mHeight, hints)

后生成的矩阵数据转换为 Bitmap 图时,会产生很大的左右两边的空白,zxing 提供了 EncodeHintType.MARGIN 选项来设置左右空白,很多时候无效,但偶然会成功,很困惑,所以追踪了一下代码,明白了其生成的原理,现以源码解析的方式整理如下。

此处,以类似“901001*C005”格式的内容来分析,编码格式为 CODE128。

1、

BitMatrix matrix = new MultiFormatWriter().encode(str,BarcodeFormat.CODE_128, mwidth, mHeight, hints);

此处没什么讲的生成条码/二维码的核心代码,zxing 使用方法可以去百度/谷歌。

2、追踪 encode 函数,其原型 MultiFormatWriter.java 中,代码如下:

public BitMatrix encode(String contents,
BarcodeFormat format,
int width, int height,
Map hints) throws WriterException {

Writer writer;
switch (format) {
  case EAN_8:
    writer = new EAN8Writer();
    break;
  case EAN_13:
    writer = new EAN13Writer();
    break;
  case UPC_A:
    writer = new UPCAWriter();
    break;
  case QR_CODE:
    writer = new QRCodeWriter();
    break;
  case CODE_39:
    writer = new Code39Writer();
    break;
  case CODE_128:
    writer = new Code128Writer();
    break;
  case ITF:
    writer = new ITFWriter();
    break;
  case PDF_417:
    writer = new PDF417Writer();
    break;
  case CODABAR:
    writer = new CodaBarWriter();
    break;
  case DATA_MATRIX:
    writer = new DataMatrixWriter();
    break;
  case AZTEC:
    writer = new AztecWriter();
    break;
  default:
    throw new IllegalArgumentException("No encoder available for format " + format);
}
return writer.encode(contents, format, width, height, hints);

}

可以看到其采用工厂模式,将任务分发到了各个实现类中,以本测试 CODE128 格式为例,其使用的是 Code128Writer 中的 encode 函数,接着追踪到该单元中。

3、

public final class Code128Writer extends OneDimensionalCodeWriter {
@Override
public BitMatrix encode(String contents,
BarcodeFormat format,
int width,
int height,
Map hints) throws WriterException {
if (format != BarcodeFormat.CODE_128) {
throw new IllegalArgumentException("Can only encode CODE_128, but got " + format);
}
return super.encode(contents, format, width, height, hints);
}
@Override
public boolean[] encode(String contents) {
int length = contents.length();
/*
省略,就是根据 CODE128 的规则,生成一个一维的数组,每个元素代表有效内容的条码表示,true 代表“条”,false,代表空,此处测试内容为 901001C005,生成的一维数组长度为 134,
*/
}
}

看到 encode(String contents,BarcodeFormat......)调用了其父类的 encode 函数,继续追踪。

4、

@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 (width < 0 || height < 0) {
  throw new IllegalArgumentException("Negative size is not allowed. Input: "
                                         + width + 'x' + height);
}

int sidesMargin = getDefaultMargin();
if (hints != null) {
  Integer sidesMarginInt = (Integer) hints.get(EncodeHintType.MARGIN);
  if (sidesMarginInt != null) {
    sidesMargin = sidesMarginInt;
  }
}

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

}

此处可以看到,我们设置的 EncodeHintsType.MARGIN 出现了,代码的具体含义就是,你要是设置了该值就取你设置的值,如果没有设置,去默认值(10),代码为:

public int getDefaultMargin() {
// CodaBar spec requires a side margin to be more than ten times wider than narrow space.
// This seems like a decent idea for a default for all formats.
return 10;
}

然后其其调用了 encode(String contents),该函数在 OneDimensionalCodeWriter 类中声明为抽象方法,下放到子类中实现,此处就是标题 3 处 Code128Writer 类中实现的 encode(String content)生成一个一维数组。

接下来关键的内容来,函数 renderResult。在该函数中计算了生成的矩阵的大小,其有你传入的宽、生成的一维数组长度、你设置的 MARGIN 三个参数共同决定,对于一维条码,高(需大于 1)并无大用。

5、

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;
int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;

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;

}

首先,inputWidth 即根据 CODE128 规则生成的一维数组的长度;此处为 134

接着,fullWidth 即实际内容宽度和你设置的空白宽度;假设,我设置 MARGIN 为 1,此处 fullwidth 为 135;

接下来,是获取输出矩阵的宽和高,用了取较大值的数学函数 max;假设我们设置的需要的条码宽和高分别为:300 和 100,此处 outputWidth 为 300,outputHeigth 为 100;

接着,关键代码,计算实际内容缩放的比例:multiple,此处可得 300/135=2,;

然后,可计算真实的左右空白:leftPadding,此处为:(300 - 135*2)/2 = 15;

然后,就是根据计算好的宽高及空白,生成矩阵。

我们可以在拿另一个例子解析下,宽设置为 270,MARGIN 设置为 0,故 multiple=2,leftPading = 0;然后生成的条码没有空白,但我们其他参数不变,宽设置为 260,得 multiple = 1;leftPading = (260 - 134*1)/2 = 62,两边有很大的空白。

结束语,之所以,zxing 会采用这种策略,就是为了保持条码中的比例,以免失真出现无法识别的条码矩阵。

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • sts
    2 引用 • 2 回帖 • 152 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 427 关注
  • Facebook

    Facebook 是一个联系朋友的社交工具。大家可以通过它和朋友、同事、同学以及周围的人保持互动交流,分享无限上传的图片,发布链接和视频,更可以增进对朋友的了解。

    4 引用 • 15 回帖 • 455 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 428 关注
  • gRpc
    10 引用 • 8 回帖 • 54 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    60 引用 • 287 回帖
  • 导航

    各种网址链接、内容导航。

    37 引用 • 168 回帖
  • 微软

    微软是一家美国跨国科技公司,也是世界 PC 软件开发的先导,由比尔·盖茨与保罗·艾伦创办于 1975 年,公司总部设立在华盛顿州的雷德蒙德(Redmond,邻近西雅图)。以研发、制造、授权和提供广泛的电脑软件服务业务为主。

    8 引用 • 44 回帖
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 35 关注
  • App

    App(应用程序,Application 的缩写)一般指手机软件。

    90 引用 • 383 回帖 • 1 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18775 引用 • 70188 回帖
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 6 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • 安全

    安全永远都不是一个小问题。

    189 引用 • 813 回帖
  • Git

    Git 是 Linux Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

    205 引用 • 357 回帖
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    9 引用 • 32 回帖 • 161 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 221 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 318 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 149 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 55 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 462 关注
  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 595 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 292 关注
  • 笔记

    好记性不如烂笔头。

    305 引用 • 780 回帖
  • 域名

    域名(Domain Name),简称域名、网域,是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称,用于在数据传输时标识计算机的电子方位(有时也指地理位置)。

    43 引用 • 208 回帖
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    40 引用 • 24 回帖