2021SC@SDUSC

目录

  • 一、State
    • 成员变量
    • latchAndAppend
    • shiftAndAppend
    • addBinaryShiftChar
    • endBinaryShift
    • isBetterThanOrEqualTo
  • 二、HighLevelEncoder
    • static final int[][] LATCH_TABLE
    • encode
    • updateStateListForChar
    • updateStateForChar
    • updateStateForPair

前言:本篇博客继续对Aztec二维码编码进行分析。


一、State

State表示有关生成当前输出所需的序列的所有信息。注意,状态是不可变的。

成员变量

变量名 说明
mode 编码的当前模式(或者,如果处于二进制移位模式,将返回的模式)
token 输出的令牌列表。如果处于二进制移位模式,此令牌列表尚未包含这些字节的令牌
binaryShiftByteCount 如果非零,则表示应以二进制移位模式输出的最新字节数。
bitCount 生成的总位数(包括二进制移位)

latchAndAppend

创建一个表示此状态的新状态,并将latch转换为(不需要不同的)模式,然后创建一个代码。

  State latchAndAppend(int mode, int value) {// 明确binaryShiftByteCount == 0;int bitCount = this.bitCount;Token token = this.token;if (mode != this.mode) {int latch = HighLevelEncoder.LATCH_TABLE[this.mode][mode];token = token.add(latch & 0xFFFF, latch >> 16);bitCount += latch >> 16;}int latchModeBitCount = mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5;token = token.add(value, latchModeBitCount);return new State(token, mode, 0, bitCount + latchModeBitCount);}

shiftAndAppend

创建表示此状态的新状态,临时切换到其他模式以输出单个值。

  State shiftAndAppend(int mode, int value) {// 明确binaryShiftByteCount == 0 && this.mode != mode;Token token = this.token;int thisModeBitCount = this.mode == HighLevelEncoder.MODE_DIGIT ? 4 : 5;// 移位仅存在于UPPER和PUNCT,这两种类型的令牌大小均为5。token = token.add(HighLevelEncoder.SHIFT_TABLE[this.mode][mode], thisModeBitCount);token = token.add(value, 5);return new State(token, this.mode, 0, this.bitCount + thisModeBitCount + 5);}

addBinaryShiftChar

创建一个表示此状态的新状态,但在二进制移位模式下创建一个附加字符输出。

  State addBinaryShiftChar(int index) {Token token = this.token;int mode = this.mode;int bitCount = this.bitCount;if (this.mode == HighLevelEncoder.MODE_PUNCT || this.mode == HighLevelEncoder.MODE_DIGIT) {// 明确binaryShiftByteCount == 0;int latch = HighLevelEncoder.LATCH_TABLE[mode][HighLevelEncoder.MODE_UPPER];token = token.add(latch & 0xFFFF, latch >> 16);bitCount += latch >> 16;mode = HighLevelEncoder.MODE_UPPER;}int deltaBitCount =(binaryShiftByteCount == 0 || binaryShiftByteCount == 31) ? 18 :(binaryShiftByteCount == 62) ? 9 : 8;State result = new State(token, mode, binaryShiftByteCount + 1, bitCount + deltaBitCount);if (result.binaryShiftByteCount == 2047 + 31) {// 字符串的长度与允许的长度相同。我们应该结束它。result = result.endBinaryShift(index + 1);}return result;}

endBinaryShift

创建与此相同的状态,但我们不再处于二进制移位模式。

  State endBinaryShift(int index) {if (binaryShiftByteCount == 0) {return this;}Token token = this.token;token = token.addBinaryShift(index - binaryShiftByteCount, binaryShiftByteCount);// 明确token.getTotalBitCount() == this.bitCount;return new State(token, mode, 0, this.bitCount);}

isBetterThanOrEqualTo

如果在所有可能的情况下“this”状态比“that”状态更好(或相等),则返回true。

  boolean isBetterThanOrEqualTo(State other) {int newModeBitCount = this.bitCount + (HighLevelEncoder.LATCH_TABLE[this.mode][other.mode] >> 16);if (this.binaryShiftByteCount < other.binaryShiftByteCount) {// 如果有,添加其他B/S编码成本newModeBitCount += other.binaryShiftCost - this.binaryShiftCost;} else if (this.binaryShiftByteCount > other.binaryShiftByteCount && other.binaryShiftByteCount > 0) {// 最大可能的额外成本(我们最终超过了31字节的边界,其他状态可以保持在该边界之下)newModeBitCount += 10;}return newModeBitCount <= other.bitCount;}

二、HighLevelEncoder

产生接近最佳的文本编码到Aztec代码使用的第一级编码中。
它使用动态算法。对于字符串的每个前缀,它确定可能导致该前缀的一组编码。我们反复添加一个字符并生成一组新的最佳编码,直到我们看完整个输入。

static final int[][] LATCH_TABLE

LATCH_TABLE显示了每对模式从一种模式转换到另一种模式的最佳方法。在最坏的情况下,这可能高达14位。在最好的情况下,每个条目的高半字表示位数。每个条目的下半个字是需要更改的实际位。

static final int[][] LATCH_TABLE = {{0,(5 << 16) + 28,              // UPPER -> LOWER(5 << 16) + 30,              // UPPER -> DIGIT(5 << 16) + 29,              // UPPER -> MIXED(10 << 16) + (29 << 5) + 30, // UPPER -> MIXED -> PUNCT},{(9 << 16) + (30 << 4) + 14,  // LOWER -> DIGIT -> UPPER0,(5 << 16) + 30,              // LOWER -> DIGIT(5 << 16) + 29,              // LOWER -> MIXED(10 << 16) + (29 << 5) + 30, // LOWER -> MIXED -> PUNCT},{(4 << 16) + 14,              // DIGIT -> UPPER(9 << 16) + (14 << 5) + 28,  // DIGIT -> UPPER -> LOWER0,(9 << 16) + (14 << 5) + 29,  // DIGIT -> UPPER -> MIXED(14 << 16) + (14 << 10) + (29 << 5) + 30,// DIGIT -> UPPER -> MIXED -> PUNCT},{(5 << 16) + 29,              // MIXED -> UPPER(5 << 16) + 28,              // MIXED -> LOWER(10 << 16) + (29 << 5) + 30, // MIXED -> UPPER -> DIGIT0,(5 << 16) + 30,              // MIXED -> PUNCT},{(5 << 16) + 31,              // PUNCT -> UPPER(10 << 16) + (31 << 5) + 28, // PUNCT -> UPPER -> LOWER(10 << 16) + (31 << 5) + 30, // PUNCT -> UPPER -> DIGIT(10 << 16) + (31 << 5) + 29, // PUNCT -> UPPER -> MIXED0,},};

encode

返回由编码为BitArray的编码器表示的文本

  public BitArray encode() {State initialState = State.INITIAL_STATE;if (charset != null) {CharacterSetECI eci = CharacterSetECI.getCharacterSetECI(charset);if (null == eci) {throw new IllegalArgumentException("No ECI code for character set " + charset);}initialState = initialState.appendFLGn(eci.getValue());}Collection<State> states = Collections.singletonList(initialState);for (int index = 0; index < text.length; index++) {int pairCode;int nextChar = index + 1 < text.length ? text[index + 1] : 0;switch (text[index]) {case '\r':pairCode = nextChar == '\n' ? 2 : 0;break;case '.' :pairCode = nextChar == ' ' ? 3 : 0;break;case ',' :pairCode = nextChar == ' ' ? 4 : 0;break;case ':' :pairCode = nextChar == ' ' ? 5 : 0;break;default:pairCode = 0;}if (pairCode > 0) {// 有四对特殊的点对中的一对。特别对待他们。// 获取两个新字符的新状态集。states = updateStateListForPair(states, index, pairCode);index++;} else {// 获取新角色的一组新状态。states = updateStateListForChar(states, index);}}// 只剩下一组状态。找一个最短的。State minState = Collections.min(states, new Comparator<State>() {@Overridepublic int compare(State a, State b) {return a.getBitCount() - b.getBitCount();}});// 将其转换为位数组,然后返回。return minState.toBitArray(text);}

updateStateListForChar

通过更新新角色的每个状态、合并结果,然后删除非最佳状态来更新新角色的一组状态。

  private Collection<State> updateStateListForChar(Iterable<State> states, int index) {Collection<State> result = new LinkedList<>();for (State state : states) {updateStateForChar(state, index, result);}return simplifyStates(result);}

updateStateForChar

返回一组状态,这些状态表示为下一个字符更新此状态的可能方式。结果状态集将添加到“结果”列表中。

  private void updateStateForChar(State state, int index, Collection<State> result) {char ch = (char) (text[index] & 0xFF);boolean charInCurrentTable = CHAR_MAP[state.getMode()][ch] > 0;State stateNoBinary = null;for (int mode = 0; mode <= MODE_PUNCT; mode++) {int charInMode = CHAR_MAP[mode][ch];if (charInMode > 0) {if (stateNoBinary == null) {// 仅在第一次需要时才创建stateNoBinary。stateNoBinary = state.endBinaryShift(index);}// 尝试通过锁定其模式来生成角色if (!charInCurrentTable || mode == state.getMode() || mode == MODE_DIGIT) {// 如果字符在当前表中,我们不希望锁定到任何其他模式,可能除了数字(仅使用4位)。在*这个字符之后,任何其他锁存都将同样成功,因此不会保存任何位。State latchState = stateNoBinary.latchAndAppend(mode, charInMode);result.add(latchState);}// 尝试通过切换到角色模式来生成角色。if (!charInCurrentTable && SHIFT_TABLE[state.getMode()][mode] >= 0) {// 如果角色存在于当前模式中,则暂时切换到其他模式是没有意义的。这永远也省不了多少钱。State shiftState = stateNoBinary.shiftAndAppend(mode, charInMode);result.add(shiftState);}}}if (state.getBinaryShiftByteCount() > 0 || CHAR_MAP[state.getMode()][ch] == 0) {// 如果您尚未处于二进制移位模式,并且字符存在于当前模式中,则进入二进制移位模式是不值得的。这永远不会比仅在当前模式下输出字符节省位。State binaryState = state.addBinaryShiftChar(index);result.add(binaryState);}}

updateStateForPair

private static void updateStateForPair(State state, int index, int pairCode, Collection<State> result) {State stateNoBinary = state.endBinaryShift(index);// 可能性1。锁存到MODE_PUNCT,然后附加此代码result.add(stateNoBinary.latchAndAppend(MODE_PUNCT, pairCode));if (state.getMode() != MODE_PUNCT) {// 可能性2.切换到MODE_PUNCT,然后附加此代码。// 除MODE_PUNCT(如上所述)外的所有状态都可以改变result.add(stateNoBinary.shiftAndAppend(MODE_PUNCT, pairCode));}if (pairCode == 3 || pairCode == 4) {// 两个字符都是数字。有时最好只加两个数字State digitState = stateNoBinary.latchAndAppend(MODE_DIGIT, 16 - pairCode)  // 数字中的句点或逗号.latchAndAppend(MODE_DIGIT, 1);             // 数字中的空格result.add(digitState);}if (state.getBinaryShiftByteCount() > 0) {// 只有当我们已经处于二进制模式时,将字符作为二进制字符才有意义。State binaryState = state.addBinaryShiftChar(index).addBinaryShiftChar(index + 1);result.add(binaryState);}}

2021SC@SDUSC Zxing开源代码(十四)Aztec二维码(三)相关推荐

  1. 2021SC@SDUSC Zxing开源代码(二)CaptureActivity代码分析-生命周期函数

    文章目录 前言 一.Android基础知识 1. Android 基本组件 2. SurfaceView .Surface与SurfaceHolder 3. Activity 生命周期 4. Andr ...

  2. 2021SC@SDUSC Zxing开源代码(十七)Zxing代码解析——一维码

    2021SC@SDUSC 目录 Code 39 Code 93 Code 128 Codabar ITF 参考资料 前言:本篇博客主要介绍一维码. Code 39 Code39是条形码的一种,也被称为 ...

  3. Zxing图片识别 从相册选二维码图片解析总结

    Zxing图片识别 从相册选取二维码图片进行解析总结 在Zxing扫描识别和图片识别的解析对象是相同的 本文分三个步骤: 1 获取相册的照片 2 解析二维码图片 3 返回结果 1) 获取相册照片 go ...

  4. 开发一个基于ZXing库以及安卓Studio的二维码扫描小程序(二)

    开发一个基于ZXing库以及安卓Studio的二维码扫描小程序(二) 下面我们做一个ZXing扫描二维码的例子,是通过安卓库的方式引用ZXing应用代码. 开发步骤 建立一个安卓工程(Project) ...

  5. C# 利用ZXing.Net来生成条形码和二维码

    本文是利用ZXing.Net在WinForm中生成条形码,二维码的小例子,仅供学习分享使用,如有不足之处,还请指正. 什么是ZXing.Net? ZXing是一个开放源码的,用Java实现的多种格式的 ...

  6. 【QR Code Generator】开源免费响应式QRcdr二维码生成网站源码

    介绍: 开源免费响应式QRcdr二维码,一款基于PHP编写的二维码在线生成系统,只需点击几下就可以生成您的个人二维码,上传您的徽标或水印,选择自定义颜色,生成多种类型,选择一个图案并下载最终的二维码图 ...

  7. Android 基于google Zxing实现对手机中的二维码进行扫描

    转载请注明出处:http://blog.csdn.net/xiaanming/article/details/14450809 我之前写了一篇关于google Zxing扫描二维码的文章,效果是仿微信 ...

  8. 用11行Python代码,实现动态二维码制作

    用11行Python代码,实现动态二维码制作 效果展示 Python实现 素材 其他工具 效果展示 Python实现 要预装myqr模块才行. windows键+R 打开cmd,输入pip insta ...

  9. python生成二维码代码_python 一行代码生成 二维码

    效果图如上:动态二维码,彩色二维码,黑白二维码: 看到别人做的炫酷二维码,瞬间心动,想动手做个 自己的炫酷二维码. github上有大神 做的框架,直接拿来用,安装工具 myqr: pip insta ...

  10. 每年扫码千亿次!微信官方开源了自家优化的二维码引擎!3行代码让你拥有微信扫码能力...

    本文转载自OpenCV团队. 十天前,微信官方开发团队在 opencv_contrib 开源了自家优化9年的二维码引擎!各位读者可编译最新版OpenCV及opencv_contrib ,直接使用! 2 ...

最新文章

  1. 刚刚!2020世界大学学术排名正式发布:中国内地144所大学上榜!
  2. 黄聪:IE6下css大bug:文字神秘消失,鼠标选择了才出现
  3. Java2WSDL 和 WSDL2Java(Axis)
  4. 开发 Eclipse 插件
  5. CSS的DIV背景图放置(兼容IE6)
  6. PHOTOSHOP中3D下拉菜单为灰色如何设置
  7. 元素周期表排列的规律_中考化学:金属活动性顺序表和元素周期表规律总结
  8. 漫步数学分析二——欧几里得空间
  9. iOS:Xcode7下创建 .a静态库 和 .framework静态库
  10. mysql数据库增删改查关键字_Mysql数据库,增删改查笔记(非常重要)-阿里云开发者社区...
  11. 高清电视开播:大多用户仍难跨入
  12. SQL注入语句(详细)
  13. 定时清理elasticsearch索引和数据
  14. 分享NetSuite CRM成功实施案例!
  15. vue动态拼接图片路径、img地址拼接问题 [模板字符串]
  16. linux开机到登陆的流程图,Linux开机自动登录root,并启动应用程序
  17. Chromium for mac(谷歌浏览器)V89.0.4336.0官方最新版
  18. 爬取女朋友用我淘宝已购买的宝贝数据,发现了她特殊的秘密...
  19. 【编译原理】:如何将控制语句翻译成四元式
  20. vue页面自适应屏幕宽高_vue组件页面高度根据屏幕大小自适应

热门文章

  1. nebulagraph exchange3.0.x
  2. kali破解wifi 密码(仅供学习)
  3. 野火指南者ESP8266模块学习
  4. 通过GDI+修改jpg文件EXIF属性
  5. 全球及中国建筑涂料市场盈利能力分析与产值规模预测报告2022版
  6. 基于Android的人脸门禁系统
  7. Spring底层原理问题
  8. .Net框架搭建之辅助模版代码生成工具
  9. Power query (Power BI)一步到位傻瓜式合并工作簿,史上最好用
  10. Chrome和360浏览器“无法翻译此网页”解决方法