[Discode] 设计Discode

简介

在本篇文章中我将一步步的阐述我设计Discode的流程以及我的思考点。虽然Discode作为一种编码仍然比较稚嫩,但作为入门自己的第一个图形编码仍然是不错的例子。

目录

  • 分析现有编码的设计
  • Discode的视觉设计
  • Discode的技术指标
  • Discode的编码设计
  • 编后语
  • 版权声明

分析现有编码的设计

当前世面上各家厂商为了用户纷纷都推出了自有的编码规范,仅仅在大陆地区而言,当前能够看到的自由编码普遍是圆形二维码,也有像是QQ小程序码的变种圆形二维码。

从这四种只有编码中我们不难观察出一个规律,大家的编码样式的元素基本都是:

  1. 图形编码环绕着Logo
  2. 四点定位

图形编码环绕着Logo

这种设计有两个好处:

  1. 具有高自由度的品牌露出的能力

开发者可以自由的定义自己的图标类型,使得用户一眼就能识别出编码对应的软件信息(比如广东省的粤核酸小程序的Logo是DNA双链+号码,用户扫描前就已经可以预测到自己扫描的是一个粤核酸的小程序)。

  1. 不占用实际编码区域

现有的二维码规范中,已经通过纠错编码的能力,来实现图片覆盖二维码后仍能识别的能力。但对于一个新生的图形编码而言,设计一个出色的纠错编码并不是一件容易的事情,即使套用现有的编码规范仍有可能因为经验不足等因素导致到后来Coding过程中出现一些不可预见的限制。因此将分开显示能够极大的规避掉初期编码水平不足给自己挖坑的风险。

有好处当然也是有坏处的:

  1. 需要开发全新的生成与识别规则

环形编码意味着不能直接复用二维码已有的生成能力也不能直接识别,所有的东西都需要从0开始。

  1. 编码容量有限

环状编码的本质就是在圆圈上作文章,比如使用点、线段等作为二进制中的1,空白作为二进制中的0,实现二进制编码成图像元素。受制于圆形的特性:一圈是360度,为了视觉识别的准确性和速度,一般都会设计为每5-10度的圆弧内记录一个编码。因此单圈的能够承载的编码都是有限的,比如小程序码就是设计了36线,54线,72线的小程序码。假如我们10度编码一位信息,则一圈最多可以编码36位二进制信息。同时自定义的编码还有长度限制,因此单圈的实际编码数量肯定是远远小于36位的。

思考:如何拓展容量?

圆形编码有两种扩大容量的方式:

1.使用更密集的图形(在更小的弧度内编码信息)

比如小程序码的36线就是每10度作为一个编码区,54线就是6.6度一个编码区,72线就是5度一个编码区。

2.扩大半径(增加圈数)

比如支付宝只有3圈编码区域,AppClips则是5圈编码区

2.四点定位

以小程序码为例,分别在左上右上左下设置了Mark Point(定位点),其实右下角的Logo也是一个定位点,不过他是一个特殊的定位点,需要使用特殊的计算方式确定真实的圆心(在此不赘述),最终微信是可以通过这四点的圆心坐标,计算出对角线交线的坐标点,而这个坐标点就是小程序码的圆心。另外通过这四个点还能确定编码的实际区域,方便进行透视变换矫正图形到正确的位置。

思考:定位点是必须的吗?

虽然定位点确实能够帮助我们进行很炫酷的图形变换来矫正图形到正确的形态,但对于刚刚入门图形编码的我来说这个也太难了吧!遂开始寻找有没有不需要定位点的图形码,没想到还真的有,那就是Apple为App小程序推出的AppClips Code。

那么问题来了,为什么AppClip码可以不要定位点?那它要怎么定位圆心?机器如何对其进行纠正?通过查阅设计文档得出的答案居然是:标准限制+人工对准。

文档地址: Human Interface Guidelines > App Clips > App Clip Codes

阅读了Apple的设计规范之后,我才悟到其实我们不需要强行考虑复杂的环境,我们完全可以设计一些标准规避到复杂环境的可能,让用户遵守标准就好了,这样子就可以规避到很多问题,极大的降低工程的技术难度,为后续的继续设计奠定了基础。

Discode的视觉设计

完成上一节的市场分析后,我们就可以开始思考一下我们的Discode到底要长什么样子了。

基于市面上的圆形码,我的初步想法是:通过定位点来定位图像,同样支持品牌Logo的露出,另外也需要支持可变容量。因此原型设计中我参考了小程序码的定位点设计,出于后期编码的简单化考虑和法务风险规避的考虑,我把小程序码右下角的官方Logo去掉,替换成为了定位点。如果日后需要增加官方Logo的话,则如下图所示可以在品牌Logo的右下角增加一个官方的小Logo。

对于可变容量我也思考了两种方向,增大圈数或者加大密度,考虑到半径的动态变化可能会对识别造成一些不可规避的难点,我还是选择了减小编码区所占用的弧度,来增加编码密度实现容量的可变性。为此我同样参考了小程序码的设计并根据圆弧的弧度为360度进行平均分割,设计了36区、72区和144区的编码区密度,其分别占用10度/编码区、5度/编码区、2.5度/编码区。为了容量和设计美观度的考虑,暂定的圈数应该为3圈,确保可以将Discode印刷于一个非常小的区块中。

Discode的编码设计

图像编码中最核心的部分之一就是数据的编码规则了,通过编码规则,我们才能将二进制的数据转换成特定的图形并组合成一块就可以生成出自己的图形编码了,反过来的就是识别的流程了,不过具体怎么做我会留到接下来的生成和识别的解析文章中来讲解。

设计编码主要是遵循以下的几步:

  1. 确定编码的使用场景(决定未来的可能场景)
  2. 确定编码的宽度(决定可以容纳多少的字符)
  3. 根据编码容量来调整实际可编码的字符
  4. 分配字符到编码规则
  5. 根据视觉调整编码规则(这一步会发生在生成Discode后才会进行,在《生成Discode》中会讲到如何调整)
  6. 确定最终编码规则 & 整理成编码字典

1. 确定编码什么字符

在这一步我们先要确定我们的使用场景:

  • 可以记录网址吗?
  • 可以记录图片吗?
  • 区分大小写字符吗?
  • 可以记录邮箱吗?
  • 我们需要考虑损毁吗?
  • 我们要考虑修复能力吗?
  • 如果要修复能力我们要支持多少百分比的恢复能力呢?
  • 中文字符要考虑吗?

这些都是需要我们根据我们的未来使用场景来预设的。在我们的本次的项目周期走,我认为网址信息和邮箱信息是必须的,因为这样子才能让Discode具有实际的落地场景。图片二维码一般都是依托于Base64来实现的,存储图片这种高密度信息,显然不是Discode的长处,因此不考虑实现。中文字符可以通过UniCode字符集实现,不过其本质还是特定字符+字母,因此实现特殊字符、大小写字母和数字的编码后就可以实现,因此可以考虑作为第二目标来实现。修复能力需要依托于支持校验的编码实现,本次开发更偏向于探究如何实现,因此参考AppClips的思路,我决定使用技术规范,来规避掉损毁的可能性,在此不考虑损毁修复的能力。

综合上述的思考:Discode的初步可编码字符就显而易见了,UniCode需要的&#;,邮箱网址需要要的@.,大小写字母和数字,一共67种字符。

2. 确定编码的宽度

按照计算机的二进制规范来看,我首先还是想到熟悉的\(2^{n}\)次方,1 Byte = 8 Bit,但是8位二进制数最大可以代表\(2^{8}\)=256个数字,对于需求中的67个数字而言冗余空间太多了,因此要进行一下缩减,那么要不就是使用7位128个,要不就是6位64个。128对于67而言冗余空间接近翻倍,太浪费了,但6位64个又存不下全部字符着实是让我有点苦恼。最终我还是选择了6位作为最终的编码长度,其中的原因主要是有两个,第一是编码密度可以达到100%,即每一位都会用于实际的编码当中,不会有冗余空间;第二则是6恰好与360的具有倍数关系,360/6 = 60,而60也恰好与2.5、5、10之间构成倍数关系,恰好满足144位、72位、36位的需求。因此出于这两点考虑选择了6位为最终的编码宽度。

3. 根据宽度来调整可实际编码的字符

确定了6位的编码宽度后,就确定了实际的容量了,即字符表最大可以存64个字符,那么大小写字符一种52个,数字字符10个,剩余2个空位。在使用场景中我有说过我的假设场景中存在用来存储邮箱地址和网址的想法,对于邮箱而言最重要的两个字符便是邮箱根地址,即@xxx.com中的@.,因此我选择了@.作为字符表最后两个空位所要代表的符号。

4. 分配字符到编码规则中

因为这次的开发中不需要考虑到纠错校验,因此分配到字符到编码规则中就很简单了,只要把所有可能出现的数字都列成表格,再一一对应填上就好了。

其中我还是有一点小考量的,开始符我设定为了.,结束符则是@,这其实是我的个人偏好而已,一个约定俗成的设定,其实换过来也是OK的。然后小写字母从000 001一直到011 010,而大写字母则是在则是最高位(第六位)设置为1,即100 001111 010,剩余的空间就用数字填空就好了。

到这里我的Discode的专属字符表就设计完成了,其实整个过程非常的简单有趣。另外一般而言,只要我们不外泄这张实际的编码表,其实基本上没人能够逆向这个图形编码的意义。(破解方法仍然是有的,只是成本问题,只要对方知道字符表大概能存哪些字符,通过一些数学统计方法仍旧是可以逆向出来的,不过对于Discode这样子的一个开源项目,其实没啥意义去逆向破解。)

Discode的技术指标

综合视觉设计和编码设计最终可以得出Discode的最终技术指标如下:

  1. 支持图像定位
  2. 支持30位的数据
  3. 支持a-z、A-Z、0-9、”@“、”.“共64种字符
  4. 支持自定义品牌Logo

编后语

说实话,其实这篇博文我觉得更像是我的一个思路的整理集,不太像一篇文笔流畅的技术解析文章,这点我确实意识到了。不过我还是想尽力分享一下我的思路出来看看能不能帮助到更多对此感兴趣的小伙伴,因为这实在是太有趣也太有成就感了。

版权声明

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。

[Discode] 为啥要设计新的二维码系统?

这是《Discode的诞生与技术细节》系列文章的第一篇文章,分别讲述了为啥我会萌生设计一个新的图形编码系统、图形编码的技术指标以及未来的文章规划。

背景

2017年初的时候,微信小程序推出了它们自己的二维码编码系统,称作小程序码,也被大众称之为菊花码。这种新的编码系统着实是令我大开眼界,后续也了解到了Snapchat和Facebook自己也有编码系统,这些奇形怪状的图形编码系统着实吸引着我去了解它们的技术原理,但可惜的是,彼时的我恰逢高三冲刺阶段,并没有这么多的精力去学习和了解这些编码系统更深层次的技术原理,只可将其放在了自己的技术待办清单中。

起因

在2022年年初的时候,我有一天偶然在电梯间看到一个支付宝的广告,发现支付宝居然也按捺不住推出了自己的图形编码系统(支付宝小程序码介绍),这再一次勾起了我蠢蠢欲动的内心欲望:做一个属于自己的编码系统。

支付宝小程序码

成果

说干就干,由于恰逢春节期间,自己有很多的个人时间,因此可以集中比较大的一块时间进行集中的研究和开发。目前已经成功开发出了一个Demo版本的编码系统,这套编码系统我将其称作为DisCode系统,分别是Disc(光盘)和Code(编码)撮合成的一个合成词,读音类同Disco(迪斯科),之所以叫做这个名字,是因为其实际的解码过程就像是读取光盘的过程,而且图形也近似于一张光盘,因此被命名为Discode系统。下图的这个就是Discode编码,编码了v2ex.com。

Discode

技术指标

  1. 支持30Bit的数据*
  2. 支持a-z、A-Z、0-9、”@“、”.“共64种字符**
  3. 支持自定义品牌ICON

*:图像中的一个圈可以编码6Bit的数据,理论上是支持\(6x(x\geq 1)\)Bit的数据

**:目前仅仅是设计了一一对应的原始编码,理论上是可以支持带纠错功能的编码的,这需要结合你的实际场景进行设计

计划

在接下来的三个月内,计划沉淀出三篇技术文章和完整可运行的项目来一步步的阐述我的思考、设计和编码流程:

  1. 《设计Discode》
  2. 《生成Discode》
  3. 《识别Discode》
  4. 《Discode生成和识别源码》

希望通过这三篇文章和全流程的项目,能够帮到一部分需要开发或者想要了解这项技术的开发者或者爱好者。

版权声明

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。