二维码为什么中文比英文占地方?

同样是几十个字,中文二维码看起来密密麻麻,英文的却疏朗很多。这不是错觉,是编码规则决定的。

做二维码的时候常遇到一个困惑:明明内容不多,生成的码已经密得看不清了;而别人的二维码扫的是个挺长的网址,看起来却稀疏得多。

原因在于二维码(QR Code)内部有四种不同的编码模式,不同字符走的通道不一样,占用的空间能差好几倍。理解这一点,你就能主动控制二维码的密度。

四种编码模式:同一条信息,大小差很多

QR 码为不同类型的字符准备了专门的编码方式,每种方式的「打包效率」不同:

模式 适用字符 每个字符占位 相对效率
数字模式0-9约 3.33 比特最高(省 40%)
字母数字模式0-9 A-Z 空格 $%*+-./:约 5.5 比特较高
字节模式其他所有字符(含中文)8 比特基准
汉字模式Shift-JIS 汉字13 比特对中日常用字略优

关键在于:一个汉字在 UTF-8 编码下占 3 个字节,也就是 24 比特。而一个英文字母只占 1 个字节(8 比特)。所以同样「20 个字」,中文要 480 比特,英文只要 160 比特——差 3 倍。

这就是中文二维码更密的最直接原因。

汉字模式能救一点,但有条件

QR 标准里有个专门的「汉字模式」,每个汉字只用 13 比特,比字节模式的 24 比特省将近一半。听起来很棒,但它有个硬性限制:只支持 Shift-JIS 编码里存在的汉字。

Shift-JIS 是日文编码,收录的汉字集合和 GB2312 或 Unicode 并不完全重合。所以:

  • 很多常见中文字能命中,能省空间;
  • 部分简体字、生僻字、以及所有非汉字字符(比如中文标点、emoji)只能退回字节模式;
  • 生成器要能在两种模式间智能切换,否则省不下多少。

实际使用中,很多生成器为了保证兼容性和正确性,干脆统一用字节模式。结果就是中文内容全部按 24 比特/字计算,二维码自然偏密。

顺便说个实用技巧:中文标点也是 3 字节。句号「。」、逗号「,」、顿号「、」都是全角字符,同样占 3 字节。如果内容里标点很多,可以改用半角标点试试,能省一些空间。

纠错等级:冗余换来的容错

二维码另一个吃空间的地方是纠错码。它用里德-所罗门算法给数据加了冗余,使得即使图案被污损一部分,仍然能还原出原始内容。四个等级:

  • L 级:约 7% 冗余,能恢复约 7% 的损坏
  • M 级:约 15% 冗余(最常用的默认档)
  • Q 级:约 25% 冗余
  • H 级:约 30% 冗余,最高容错

冗余是实打实占地方的。同样是版本 10(57×57 格),L 级能存 271 字节,H 级只能存 119 字节——少了将近 56%。

所以如果你的二维码只需要印在屏幕上扫,用 L 或 M 就够了,图案会明显稀疏一些、更好扫。只有在二维码要印在可能磨损的实物上、或者中间要放 logo 时,才值得用 Q 或 H 级。

中间放 logo 的原理正是如此:logo 遮住的区域被当作损坏,靠 H 级那 30% 的冗余补回来。如果用 L 级再放 logo,基本就扫不出来了。

版本:二维码的「尺寸档位」

QR 码一共 40 个版本,版本 n 的边长是 4n + 17 个格点:

  • 版本 1:21 × 21
  • 版本 2:25 × 25
  • 版本 10:57 × 57
  • 版本 20:97 × 97
  • 版本 40:177 × 177

容量从版本 1 的几十字节,一路涨到版本 40 的 2953 字节(L 级、字节模式)。生成器会根据你的内容长度自动选最小的够用版本。

这里有两点值得注意:

  • 格点数量是边长平方增长的。 版本从 20 涨到 40,边长只多了不到一倍,但格点数多了 3.3 倍。所以高版本二维码的单个格点会非常小。
  • 格点太小就扫不出来。 理论上每个格点至少要占 2 到 3 个像素,识别才稳定。如果你的内容太多导致版本冲到 20 以上,打印尺寸又不大,实际很可能扫不出来。

实用结论:让二维码更好扫

想让二维码又清楚又好扫,按这个优先级优化:

  • 缩短内容。 这是最有效的手段。网址能短就短,参数能删就删,中间加个短链接跳转是最常见的做法。内容减一半,版本可能降好几级。
  • 降低纠错等级。 屏幕展示用 L 或 M,不要无脑用 H。只有需要放 logo 或印在易损材质上才用高等级。
  • 保证静区。 二维码四周必须留出至少 4 个格点宽的白边(静区),这是识别算法定位二维码边界用的。裁掉白边是识别失败的头号原因,比清晰度问题更常见。
  • 留足像素。 每个格点至少 4 像素比较稳妥,也就是版本 10(57 格)至少要 228 像素宽。
  • 别用小字号的位图。 如果一定要在图片里嵌二维码,导出时用足够的分辨率,或者直接用矢量格式(SVG)避免缩放糊掉。

怎么知道自己的二维码有多密

两个办法:

一是生成的时候看工具给出的版本号——版本越低越好扫。如果用二维码生成器,它会显示当前内容占用的版本和字节数,你可以边改内容边看版本变化,直观感受「删掉几个字能降一个版本」。

二是拿现成的二维码去二维码解码看看它的版本、纠错等级和内容类型。如果你看到一个号称很长的内容却是低版本的二维码,多半是内容里有短链接。

两个工具都在浏览器本地运行,生成的图片、上传的图片都不经过服务器。

一句话总结

二维码的密度 = 内容字节数 ÷ 编码效率 + 纠错冗余。 中文按 3 字节算、标点也按 3 字节算,所以中文码天然更密;想变稀疏,最有效的办法是减内容和降纠错等级,而不是换生成工具。

相关工具