首页 > 其他分享 >手绘二维码

手绘二维码

时间:2024-06-10 10:37:58浏览次数:24  
标签:编码 纠错 10 二进制 纠错码 二维码 手绘

看到二维码,很容易猜到黑白相间的小方格就是二进制比特。那么这些比特是怎么得到的?小方格又是按照什么规则排布的?今天咱们就从零开始将一个 url 画成二维码。

考虑到大多数人可能不太了解二维码,所以先讲下基础概念。你也可以先看看左耳朵耗子写的二维码的生成细节和原理

版本

二维码一共有 40 个尺寸,官方叫作版本 Version。最小的 Version 1 是 21 × 21 的矩阵,Version 2 是 25 × 25 的矩阵 … 每增加 1 version,就增加 4 的尺寸。最高是 177 × 177 的矩阵(Version 40)。

纠错

根据日常使用经验,无论是残缺、遮挡还是污损,二维码都能够被正确识别,这得益于二维码的纠错机制。

纠错是通过纠错码实现的,当我们将源数据编码后,会采用一种纠错算法算出编码结果对应的纠错码,连同编码结果一起填充到二维码。

规范里明确了四个纠错等级,不同等级的纠错比例不同。

每个版本的纠错码个数都是固定的,比如 version 1-L 需要 7 个纠错码,version 1-M 需要 10 个纠错码,版本越大、数据越多、等级越高,需要的纠错码就越多。

结构

二维码可以简单划分为三个部分:固定的功能区(用于定位)、固定的格式信息区(比如二维码用的纠错等级和版本信息)、数据区。

二进制数据都是严格按 8 位一组填入数据区的,每一组称为一个 codeword。如果数据区的格子数不是 8 的倍数,就会剩下留白(remainder)。每个版本的功能区、格式信息区和留白的位置及其占用的面积都是固定的。

更详细的划分可以参考规范里的这张图:

编码

理论上凡是可以被编译为二进制的数据,都可以用二维码来表示,只要有相应的解码程序即可。规范里规定了几种国际通用的编码模式:

比如 Numeric 仅支持 0 ~ 9 的数字,它的编码规则是:将数据字符串拆分为每三个一组,每组作为一个十进制的百位数,然后转化为 10 位二进制。为什么是 10 位呢,因为 2^10 = 1024,恰好能覆盖最大的百位数 999。如果最后一组只有两位,则转化为 7 位二进制,如果只有一位,则转化为 4 位二进制。

Alphanumeric 支持 45 个字符,0 ~ 9、A ~ Z 和几个特殊字符。

Alphanumeric 的编码规则是:根据上表查出每个 char 对应的 value,然后两两分组,按 A * 45 + B 算出一个值,并将这个值转化为 11 位二进制。如果最后一组只有一位,则将 value 转化为 6 位二进制。

Byte 模式的编码规则最简单,就是针对单字节字符集(例如 ISO-8859-1)的编码,每个字符恰好用 8 个比特表示。

我们还可以针对不同的数据片段采用不同的编码模式,这就是混合模式。

Bit Stream

二维码包含的二进制串具体是由以下几个部分组成的:

最开头一定是编码模式,是固定的 4 位(见编码一节的表格)。

接下来是原字符的长度,不同版本和不同编码模式用多少个比特表示长度是不一样的,具体是几个,规范里有明确的规定。毕竟二维码要在有限的空间里容纳更多的信息,就不能浪费比特,用过长的二进制去表示一个较小的值。

然后就是对数据按照指定的编码模式编译出的二进制序列。如果以上三部分的数据长度不是 8 的倍数,那么必须添零凑整(terminator)。

上述数据不见得能填满整个数据区,那么剩余的空间就用两个补齐码(11101100、00010001)交错填满。这两个补齐码是规范指定的。

以上整个比特串作为输入,用纠错算法输出特定个数的纠错码,二者相接,就是整个二维码数据区的数据了。

------------------ 分割线 ------------------

接下来,咱们就选用最小的版本,和最低的纠错等级,用 Alphanumeric 模式将 HTTP://I.MEITUAN.COM 这个字符串画成一个二维码。

Step 1 编码

查表可以得到每个字符对应的码点,然后两两分组,刚好分成 10 组:(17, 29)(29, 25)(44, 43)(43, 18)(42, 22)(14, 18)(29, 30)(10, 23)(42, 12)(24, 22)。

按照 A * 45 + B 算出:794, 1330, 2023, 1953, 1912, 648, 1335, 473, 1902, 1102。

然后将每个数字依次转化为二进制(toString(2)):01100011010 10100110010 11111100111 11110100001 11101111000 01010001000 10100110111 00111011001 11101101110 10001001110。

Alphanumeric 的 mode indicator 是 0010,在 version 1 里需要 9 个比特表示长度(20 => 000010100),将它们添加到头部:0010 000010100 01100011010 10100110010 11111100111 11110100001 11101111000
01010001000 10100110111 00111011001 11101101110 10001001110。

按 8 位一组重排,添 0 凑整:00100000 10100011 00011010 10100110 01011111 10011111 11010000 11110111
10000101 00010001 01001101 11001110 11001111 01101110 10001001 11000000

version 1-L 共有 26 个 codeword,其中有 7 个纠错码(error correction codeword),那么 data codeword 应该有 19 个,目前我们只有 16 个,因此剩下 3 个需要用补齐码凑足:00100000 10100011 00011010 10100110 01011111 10011111 11010000 11110111
10000101 00010001 01001101 11001110 11001111 01101110 10001001 11000000
11101100 00010001 11101100

然后算出 7 个纠错码:11010100 01110000 01110111 10010001 00101110 10010101 11001111。(我是用 node-qrcode 反算出来的,搞不懂那个纠错算法)。

最终我们得到了整个编码结果:

Step 2 填充功能区

这一步最简单,按照规范里的规定画即可。为了便于区分,用淡紫色表示功能区的白色区域。

Step 3 填充数据区

将数据按 8 位一组,从右下角开始蛇形往复填入 2 × 4 的矩形。具体怎么填规范里有明确规定,upwards 方向,将第一个数填入位置 7,第二个数填入位置 6 ... 这里是略有点坑的,因为不是从图中所示的 0 到 7,而是反过来的。方便起见,我们将数据倒过来,再按 0 ~ 7 的顺序依次填入。

Step 4 Masking

masking 的作用是使二维码的分布更加均匀。具体操作就是将数据区和 mask pattern 对应位置的比特做异或运算。比如数据区第 8 行第 10 列是白色 0,mask pattern 第 8 行第 10 列是黑色 1,异或运算的结果是黑色 1,那么就将数据区第 8 行第 10 列改成黑色。官方规定了八种 mask pattern(000 ~ 111),我们选用 000。

Step 5 填充格式信息

对所有的版本,格式信息都是固定的 15 位。其中两个是纠错等级,三个是 mask pattern,剩下十个是纠错码。

可以想象,没有格式信息,根本无法进行解码。因此格式信息非常重要,会重复画两次(类似于双机房备份)。

左下角那一列开头是永远固定的占位符。

格式信息也需要经历纠错码 + masking 的处理。

同样的,应该反过来,从位置 14 开始填。当然,也可以先把字符串倒过来。

最终结果:


————————————————————————————————————

本文写于 2019 年

标签:编码,纠错,10,二进制,纠错码,二维码,手绘
From: https://www.cnblogs.com/kidney/p/18240202

相关文章

  • Vuforia AR篇(七)— 二维码识别
    目录前言一、什么是Barcode?二、使用步骤三、点击二维码显示信息四、效果前言在数字化时代,条形码和二维码已成为连接现实世界与数字信息的重要桥梁。Vuforia作为领先的AR开发平台,提供了BarcodeScanner功能,使得在Unity中实现条形码和二维码的识别变得简单而高效。本......
  • 二维码生成器 ZXing.Net 组件应用
    c#二维码生成器(ZXing.Net)实现安装组件CodeusingSunny.UI;usingSystem;usingSystem.Collections.Generic;usingSystem.Drawing;usingSystem.Drawing.Imaging;usingSystem.Windows.Forms;usingZXing;usingZXing.Common;usingZXing.QrCode.Internal;namespace......
  • 【MISC】一道假的二维码题目学习zxing库[python解读二维码]
    引言这道题目的考点是文件格式、双图差值、Ook!编码、PRC等,我做这题的重点是复习巩固python读取二维码zxing库的使用。例题┌───────────────────────────────────────────────────┐│马老师的秘籍......
  • 记一次读取halcon二维码模型文件的报错
    C#中使用的halcon的dll版本为17.12二维码模型是通过halcon软件保存的,halcon软件版本为20.05.前后使用的halcon版本不一致,导致程序中读取模型一直报错“HALCONerror#8860:Invalidheaderin2ddatacodemodelfileinoperatorread_data_code_2d_model”  ChatG......
  • Qt-qrencode开发-生成、显示二维码
    Qt-qrencode开发-生成二维码......
  • vue项目使用qrcode插件生成二维码
    下载npmiqrcodejs2--save导入importQRCodefrom'qrcodejs2'使用<divclass="qrcode"ref="qrCodeDiv"></div><script>importQRCodefrom'qrcodejs2'exportdefault{data(){return{},......
  • Java中生成二维码转为base64存入MySQL数据库中
    1.引入架包<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.4.1</version></dependency><dependency><groupId>com.google.zxing</groupId>......
  • 二维码生成器,一个支持多文件在线转二维码的的工具,免费二维码生成器
    随着科技的飞速发展,二维码已成为我们生活中不可或缺的一部分。从支付到信息分享,再到活动报名,二维码以其独特的优势,为我们带来了极大的便利。在众多二维码生成器平台中,易易二维码凭借其丰富的功能和卓越的性能,逐渐崭露头角,成为众多用户的首选。本文将对易易二维码生成器平台工具的......
  • 二维码生成器,连接物理与数字世界的桥梁
    在这个数字化时代,二维码作为信息传递的桥梁,已悄然渗透到我们生活的方方面面,从支付交易、信息查询到社交互动,无所不在。易易二维码生成器,正是这样一款集多功能于一体的在线工具,它不仅简化了从链接、图文到文件的转化过程,还融入了设计美学与数据分析功能,成为了企业和个人高效传播信......
  • 生成二维码
    需要的依赖<!--生成二维码所需依赖--><!--https://mvnrepository.com/artifact/com.google.zxing/core--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId&g......