使用方法
- 二维码代码生成器URL 打开时输入框里已经放好示例
https://liuquan.net/wenbengongju/,共 33 个 UTF-8 字节;结果区直接给出 V3、29×29 模块的矢量二维码,上方五张卡显示纠错等级 M、掩码 111、数据占用 78.4%。 - 输入上限是 2953 字节(V40 在 L 级下的字节容量)。纯 ASCII 网址 1 字符 1 字节,也就是 2953 个字符;超过时页面报出实际字节数、当前等级的上限,并建议降低纠错等级,而不是悄悄截断。
- 输入框按 Ctrl + Enter(macOS 用 Cmd + Enter)触发生成,Enter 本身留给换行;纠错等级下拉与模块像素数字框(1~16 的整数)一改动就立即重算。
- 六个按钮分别是「生成二维码」「载入示例」「清空」「下载 SVG」「导出 CSV」「复制对照表」。下载得到的是矢量
.svg:示例的 841 个模块位被合并成 231 段连续黑块,只有一个<path>元素,放大到印刷尺寸不会出现锯齿。 - 下方是 40 行容量对照表:默认只显示 12 行,点「加载更多」展开全部;「导出 CSV」下载带 BOM 的表格,Excel 打开中文不乱码;「复制对照表」把整表以 TSV 写入剪贴板。
二维码代码生成器URL 能解决什么问题
一是把网址变成可以印刷的矢量码。输出不是位图,而是一条 SVG 路径:示例里 29×29 的模块矩阵有 841 个模块位,其中 410 个是黑模块(48.8%),合并后只剩 231 段连续色块、d 属性 3067 个字符。因此同一份结果放包装盒、易拉宝、名片上都能等比放大。
二是先把网址的长度算成字节,再决定印多大。二维码的容量单位是字节而不是字符:示例 33 个 ASCII 字符刚好 33 字节,落进 V3(29×29);同样 33 个字符若全是汉字则是 99 字节,会跳到 V5(37×37)。边长从 29 涨到 37,码面积增加约 63%。本页把「字符数 / UTF-8 字节数 / 落到哪个版本 / 边长」放在同一屏里,避免印完才发现码比预想的大一圈。
三是把纠错等级与容量的账摆到台面上。V1 在 L/M/Q/H 四级下的字节容量是 17/14/11/7,V3 是 53/42/32/24,V40 是 2953/2331/1663/1273。等级越高越抗污损,但同一条网址可能因此撑到更大的版本;40 行容量表就是用来查这笔账的。
四是给「扫码即跳转」留一道说明。二维码里存的只是字节,扫码器把内容当作 URL 打开。把 javascript:、data: 这类伪协议印成码,扫码的人点开就会执行脚本或读取本地文件。本页按字节模式如实编码任何文本,所以这类内容要靠自己在印刷前核对协议。
本页不做这几件事:不做摄像头读取与解码,那是 二维码代码读取上传;不做 WiFi、vCard、菜单这类带前缀协议的结构化载荷,它们各自有专门的页面(见文末「相关工具」);也不做 Logo 挖空贴图。
原理与规则说明
编码路径只有一条。文本先经 TextEncoder 编成 UTF-8 字节,再按 ISO/IEC 18004 的字节模式(模式指示符 0100)拼位流:4 位模式 + 8 位或 16 位字符计数 + 每字节 8 位数据 + 最多 4 位终止符,补零到字节边界后,用 0xEC 与 0x11 两个填充码字交替填满数据区。
版本怎么定。版本 v 的模块边长是 4v+17:V1 是 21×21,V3 是 29×29,V10 是 57×57,V40 是 177×177(31329 个模块位)。数据码字数等于「总码字数 − 每块纠错码字数 × 块数」,选版本就是找最小的 v 使 4 + 计数位 + 8 × 字节数 ≤ 数据码字数 × 8。示例 33 字节在 M 级下最小可行版本是 V3:44 个数据码字 = 352 位,实占 4 + 8 + 264 = 276 位,占用率 78.4%。
纠错走 GF(2⁸)。本原多项式 0x11D(十进制 285)。每块先用生成多项式 g(x) = ∏(x − αⁱ)(i 从 0 到 ecw−1)做多项式除法取余,得到纠错码字,再按「数据码字逐列交织 + 纠错码字逐列交织」拼回一条流。V1 四个等级都是 1 块,纠错码字数分别是 7/10/13/17;因为 RS 每块最多纠正 floor(纠错码字/2) 个符号,V1 四级能纠的码字是 3/5/6/8 个,占全部 26 个码字的 11.54%/19.23%/23.08%/30.77%。V3-M 是 1 块 26 个纠错码字,可纠 13 个,占 70 个码字的 18.57%。
掩码为什么要试 8 种。数据直接铺进去会撞出大片同色区域和酷似定位图形的花纹,扫码器难以定位。规格定义 8 种掩码(编号 000~111),按 (i,j) 的奇偶、模 2、模 3 规律对数据区取反;本页把 8 种全排一遍,按 N1(同色连续段)、N2(2×2 同色块)、N3(1:1:3:1:1 花纹)、N4(黑白比例偏离 50%)四条规则加权罚分,取最低者。示例选中的是掩码 111。
格式信息与版本信息也带纠错。格式信息是 5 位数据(2 位纠错等级 + 3 位掩码)的 BCH(15,5),生成多项式 0x537,末尾异或 0x5412 以免出现全零;V7 及以上还要写 18 位 BCH(18,6) 版本信息,生成多项式 0x1F25。这两段冗余让扫码器在图像轻微旋转、倾斜时先把等级与掩码读对,再去解数据。
静区不能省。规格要求码区四周至少留 4 个模块的空白。示例 29×29 加上静区后画布是 37×37 模块,默认 4 像素/模块即 148×148 像素;本页用 viewBox="-4 -4 37 37" 把静区画进同一条 SVG,下载后不要裁掉这圈白边。
黑模块比例不会正好 50%。掩码只对数据区取反、不动定位图形和定时图形,所以比例总会有偏差:示例 410/841 = 48.8%。N4 规则罚的就是这个偏差,规格希望它落在 50% 附近。
完整示例(数值均为实测)
与页面默认值完全一致:输入 https://liuquan.net/wenbengongju/,纠错等级 M,模块像素 4。实测结果:
- UTF-8 字节 33(ASCII 1:1),落到 V3,边长 4×3+17 = 29 模块;
- 位流占用 4 + 8 + 33×8 = 276 bit,V3 在 M 级的数据容量是 44×8 = 352 bit,占用率 78.4%;
- 数据码字 44、总码字 70,分块为 1 块 × 26 个纠错码字;
- 8 种掩码逐一排布后选中 掩码 111,黑模块 410 / 841 = 48.8%;
- 输出为单条
<path>,共 231 段连续色块,d属性 3067 字符,画布 148×148 像素(模块像素 4)。
把几组常见网址放进来对照,可以看到真正决定版本的是字节数:
| 网址 | 字符数 | UTF-8 字节 | 版本 | 尺寸 | 掩码 |
|---|---|---|---|---|---|
| https://liuquan.net/ | 20 | 20 | V2 | 25×25 | 011 |
| https://liuquan.net/wenbengongju/ | 33 | 33 | V3 | 29×29 | 111 |
| https://www.example.com/a/b?x=1&y=2 | 35 | 35 | V3 | 29×29 | 011 |
| https://liuquan.net/search?q=%E4%BA%8C%E7%BB%B4%E7%A0%81 | 56 | 56 | V4 | 33×33 | 100 |
| https://liuquan.net/?q= 后接 120 个 a | 143 | 143 | V8 | 49×49 | 011 |
| https://liuquan.net/?q= 后接 40 个「中」 | 63 | 143 | V8 | 49×49 | 110 |
注意最后两行:字符数 143 与 63 的输入,字节数都是 143,落点同为 V8、掩码却不同。前者是 143 个 ASCII 字符,后者是 40 个汉字(40×3 = 120 字节)加上 https://liuquan.net/?q= 的 23 字节。掩码不同是因为数据位不一样,掩码是「按数据算出来的最佳取反方案」,不是固定值。
输入范围与容量对照表
输入上限 2953 字节(V40 在 L 级下的字节容量);若把纠错等级调到 H,上限降到 1273 字节,相差 1680 字节。字符计数指示位在 V1–V9 是 8 位(最多 255 字节),V10–V40 是 16 位,所以 256 字节以上的网址会自动落到 V10 及以后。
同一个版本在四个等级下的取舍差别很大,先看最小的 V1 和示例所在的 V3:
| 版本 | 边长 | 容量 L/M/Q/H(字节) | 纠错码字占全部码字 | 可纠正码字占比 |
|---|---|---|---|---|
| V1 | 21×21 | 17 / 14 / 11 / 7 | 26.92% / 38.46% / 50.00% / 65.38% | 11.54% / 19.23% / 23.08% / 30.77% |
| V3 | 29×29 | 53 / 42 / 32 / 24 | 21.43% / 37.14% / 51.43% / 62.86% | — / 18.57% / — / — |
右侧两列要一起看:纠错码字占比越高,说明卷进冗余的码字越多;但 RS 每块最多纠正 floor(纠错码字/2) 个符号,所以真正能纠回来的码字比例大约是纠错码字占比的一半。V1-H 的 17 个纠错码字对应 8 个可纠符号,占 26 个码字的 30.77%;V1-M 的 10 个纠错码字只对应 5 个可纠符号、19.23%。这就是「等级换容错」的实际汇率。
完整 40 行容量表在页面上方(默认显示 12 行,可展开,也可导出 CSV 或复制为 TSV),这里不再重复。
边界、精度与常见误用
- 超限就报错,不截断。超过上限时页面给出「实际字节数 / 当前等级上限 / 建议降级」三件事。截断后生成的码只包含半段网址,却和完整结果长得一样确定,比直接报错更容易造成误印。
- 字节数不等于字符数。UTF-8 下一个汉字 3 字节:63 个字符的中文网址实测 143 字节,比 143 个 ASCII 字符占的版本完全一样,但字符数少一半多。网址里若含中文、空格、
&、=,先做百分号编码再贴进来更稳妥(见 URL编码),注意编码后还会变长——一个中文变成%E4%BA%8C这样 9 个字符。 - 纠错等级不是越高越好。V3 从 L 的 53 字节掉到 H 的 24 字节。纯网址二维码通常用 M:它让示例的 33 字节仍留在 V3,同时留出约 18.57% 的可纠正码字。只有小尺寸、易磨损、易脏的载体(如贴纸、金属铭牌)才值得升到 Q 或 H。
- 模块像素太小会在屏幕上糊掉。1 个模块只占 1 像素时,显示器的抗锯齿与截图缩放会把相邻模块糊成一个灰块,扫码器难以二值化。默认 4 像素/模块对应示例 148×148 像素,是最省事的选择;需要印刷则应导出 SVG 后按物理尺寸放大,而不是把 148 像素的位图拉大。
- 静区被裁掉会直接扫不出。示例的 37×37 画布里有 4 个模块是纯白边框(
viewBox="-4 -4 37 37")。把它裁成 29×29 只留码区,扫码器就会找不到码的边界;排版时务必让白色背景延伸出去。 - 非 http(s) 协议不要印。二维码代码生成器URL 只做编码、不做协议白名单,任何文本都会如实写进码里。印之前请确认内容以
http://或https://开头;伪协议一旦印出来,扫码者点开就是执行。 - 二维码的容量与「纠错能力」不是一回事。容量表里的 2953 字节是数据码字能承载的字节数;纠错能力说的是这些字节被遮挡或污损后还能不能读回来,靠的是额外的纠错码字,不占容量表里的数字。
- 全部计算在浏览器本地完成。文本不上传服务器(可在开发者工具 Network 面板自查),刷新即清空;复制与下载依赖剪贴板 API 与
data:URI,被浏览器拒绝时会给出具体提示而不是静默失败。
常见问题
为什么网址里加一个汉字,二维码就变大了一圈?
因为容量是按 UTF-8 字节算的,而一个汉字占 3 字节。示例的 33 字节网址落在 V3(29×29);如果同样长度换成 11 个汉字(33 字节)也还是 V3,但若把 33 个 ASCII 字符全换成汉字就会变成 99 字节,越过 V3 在 M 级的 42 字节上限,跳到 V5(37×37)。边长从 29 涨到 37,码面积增加约 63%。更麻烦的是 URL 里的汉字通常要先做百分号编码,编码后一个汉字会变成 %E4%BA%8C 这样的 9 个字符——所以「链接里少放中文」是缩小二维码最直接的办法。
纠错等级选 H 是不是最保险?
抗污损是更保险,代价是容量骤降。V1 四级容量是 17/14/11/7 字节,V3 是 53/42/32/24 字节,V40 是 2953/2331/1663/1273 字节;换句话说,同一条网址升到 H 可能直接跨到更大的版本,码面积反而变大。纯网址二维码建议留在 M:示例 33 字节在 M 级仍落在 V3,可纠正码字占全部码字的 18.57%(1 块 26 个纠错码字,可纠 13 个)。只有贴在容易磨损的载体上时,才值得用 H 换来更高的冗余。
下载的 SVG 能直接拿去印刷吗?静区要留多少?
能,但有两个前提。第一,不要裁边:示例的 SVG 画布是 37×37 模块,其中码区只有 29×29,外面那 4 个模块的纯白边就是规格要求的静区,裁掉会直接导致扫不出。第二,按物理尺寸而不是像素尺寸去缩放——SVG 是矢量,设置到 3 厘米或 10 厘米都清晰,但最终印刷尺寸要保证单个模块不小于约 0.4 毫米,否则手机摄像头在小尺寸下分不清相邻模块。示例 29 模块的码区,印到 12 毫米以上就有约 0.41 毫米/模块。
模块像素设成 1 或 2 为什么容易扫不出来?
模块像素只是「1 个模块占几个屏幕像素」,不影响码本身。设成 1 时示例只有 37×37 像素,屏幕上的抗锯齿会把相邻的黑白模块抹成灰,扫码器二值化时边界含糊;截图、缩放、浏览器缩放都会进一步破坏它。默认的 4 像素/模块(148×148 像素)在手机上足够清晰,也便于直接截图分享。要印刷就别用屏幕像素方案,直接导出 SVG 按物理尺寸放大。
二维码里放什么内容最危险?
危险的不是「内容长」,而是「内容会被扫码器当命令执行」。二维码里存的只是字节,扫码器识别出 URL 就直接打开,所以 javascript:(在部分内置浏览器里执行脚本)、data:(把整页内容藏在链接里,常被用来伪造登录页)、file:(读取本地文件)这三类伪协议风险最高。本页按字节模式如实编码任何文本,不做协议白名单,因此印之前请自己确认内容以 http:// 或 https:// 开头。
2953 字节这个上限是怎么来的?
它是 V40(规格允许的最大版本,177×177 模块)在 L 级下的数据字节容量。V40 总码字 3706 个,L 级的纠错码字要占掉一部分,剩下的数据码字乘以 8 再扣掉 4 位模式指示符、16 位字符计数与 4 位终止符,就得到 2953 字节。换成 H 级同样的算法只剩 1273 字节。所以上限不是一个拍脑袋的整数,而是「最大版本 + 当前纠错等级」共同决定的:等级一变,上限立刻跟着变,页面在超限提示里会同时给出这两个数。
为什么掩码不是固定值,同一段内容每次结果会不会变?
掩码是按数据算出来的:8 种掩码各排一遍,用 N1 同色连续段、N2 2×2 同色块、N3 1:1:3:1:1 花纹、N4 黑白比例偏离 50% 四条规则算加权罚分,取罚分最低的那个。所以同一段内容 + 同一等级 + 同一实现,结果永远一致,不会随机变——示例每次都选到掩码 111。反过来,内容差一个字节,选中的掩码就可能从 111 变成 011(对照表里 143 字节的两行就是这样)。这也解释了为什么不能「统一套一个掩码」:固定掩码会让某些内容撞出大片同色区,降低扫码成功率。
这个页面跟站内其它二维码工具怎么分工?
本页只做一件事:把 http(s) 网址按字节模式编成矢量 SVG,并把版本、纠错等级、掩码、字节容量摊开给你看。要读码(从图片里解出内容)用 二维码代码读取上传;要在码里贴 Logo 用 二维码生成器(带Logo);要生成 WiFi 配置码(WIFI: 前缀)用 WiFi二维码代码生成器;要把 vCard 通讯录写进码里用 vCard二维码代码生成器,它们走的是各自的结构化前缀协议,与纯网址码互不替代。
相关工具
二维码代码生成器URL 只负责 http(s) 网址这一种载荷,也不做解码;需要读码、贴 Logo、WiFi 或 vCard 形态时用下面这些页面。
- 二维码代码读取上传:反向操作——从截图或图片里读回二维码内容,用来验证刚生成的码到底能不能扫。
- 二维码生成器(带Logo):在码中心挖空一块再贴图,适合需要露出品牌标识的场合。
- WiFi二维码代码生成器:把 SSID 与密码编成
WIFI:前缀的码,扫一下连网。 - URL编码:网址里含中文、空格或
&时先做百分号编码,再回来量字节数。 - URL解析:把长链接拆成协议、主机、路径、查询串,方便判断哪一段最占字节。
- 字符数统计工具:数清一条网址有多少字符——注意它数的是字符,二维码要的是字节,两者在含中文时不同。
- Base64编码:需要把 SVG 内联进 HTML 或 CSS 时,先转成 Base64 数据 URI。