很多开发者以为把文字变成二维码很简单:输入文本、选个颜色、点生成。但真正去看生成库的源码后会发现,二维码对文本的编码方式远比直觉复杂,三种模式之间的容量差距非常明显。

我封装过一个基于 qrjs2 的小工具,它调用 QRCode.generatePNG(text, options)。通读代码后,最意外的发现是:QR 规范并不会直接存字符串,而是根据字符内容自动选择编码模式。判断逻辑大致如下:

如果是纯数字,进入数字模式(MODE_NUMERIC),每 3 个数字只占 10 bit;如果是 A-Z、0-9 以及 $ % * + - . / : 这些字符,进入字母数字模式(MODE_ALPHANUMERIC),每 2 个字符占 11 bit;其余所有字符,包括小写字母、中文、符号,都落入字节模式(MODE_OCTET),每个字符占 8 bit。

这里有一个容易忽略的坑:字母数字模式只支持大写字母,不支持小写。这意味着一个常见 URL,比如 https://begoodtool.com/qrcode,因为开头有 "https" 的小写字母,无法进入字母数字模式,只能选择最贵的字节模式。与数字模式相比,字节模式每字符多占 1 倍以上;即使和字母数字模式相比,也多占约 45% 的容量。

所以现实中的大部分二维码——网址、邮箱、自由文本——几乎都在用最占空间的方式编码。这不是某个库的 bug,而是二维码标准本身的设定。知道这一点后,下次生成二维码时不妨想想:输入内容里的大小写,其实已经在为二维码容量买单。