信息的传递从来不只是单向的文字流动。在数字与物理两个维度的交界处,始终存在一个根本需求:让抽象的数据可以被视觉感知,让可见的符号能够被机器理解。将一段信息编织成由明暗模块构成的图案,再从这幅图案中还原出它原本承载的意义——这种编码与解码的循环,本质上是人类在追求信息高效流转过程中,在"书写"与"阅读"之外开辟的第三条路径:让机器代替人眼,完成信息的即时转译。

信息不应当被禁锢在单一的介质或渠道之中。无论是屏幕上跳动的像素,还是纸张上沉淀的墨迹,都可以成为信息的忠实载体。通过约定一套公开、统一的符号规则,使图像承载数据,使扫描还原含义,我们得以在触不可及的比特与可感知的原子之间,架起一座双向通行的桥梁。这不仅是技术的演进,更是信息民主化的一种朴素表达:任何人都可以成为信息的发布者,任何人也可以成为信息的获取者,无需键盘,无需打字,只需一瞥。

视觉编码与解码的实现遵循两条互为镜像的方法论路径:编码(生成)和解码(识别)。两者共享同一套符号规则体系,但处理方向相反。

编码路径(生成)

第一步:明确待编码的原始信息。 信息可以是任意文本或统一资源定位符。系统首先判断信息的长度和所使用的字符集,这将直接影响后续编码方案的选择——不同字符集对应不同的编码效率,长文本则需要更高版本的数据结构来容纳。

第二步:选择纠错策略。 纠错能力决定了编码图案在受到遮挡、污损或光线干扰时仍能被正确识别的程度。纠错级别越高,冗余数据越多,图案中模块的密度也越大,可容忍的物理损伤比例也相应提高。需要在信息容量和容错性之间做出权衡:对用于印刷张贴的场景应选择较高的纠错级别,对仅限屏幕展示的场景则可适当降低。

第三步:设定视觉输出参数。 包括输出图案的尺寸、前景色与背景色。前景色与背景色之间必须保持足够高的对比度,以确保识读设备能够准确区分每个模块的明暗状态。对比度不足是导致识别失败的最常见原因之一。

第四步:执行编码运算。 将原始信息按既定编码规则转换为由明暗模块构成的二维数据矩阵,并在矩阵中嵌入定位图案(用于确定方向)、时序图案(用于确定模块坐标)和纠错码字(用于数据恢复),最终输出为可供显示、打印或分发的图像格式。

解码路径(识别)

第一步:获取待识别图像并转换为位图。 将用户提供的图像文件加载为内存中的位图表示,使其能够以逐像素的方式被程序访问。读取时需将图像数据转换为标准化的像素阵列格式。

第二步:提取像素阵列。 将位图绘制到离屏图像缓冲区中,逐行读取每个像素的颜色分量值,构建可供定位算法和分析算法处理的原始数值阵列。

第三步:执行定位检测与内容解码。 在像素阵列中搜索定位特征图案(通常表现为位于三个角上的特定几何结构),以此确定编码区域的边界、朝向和透视变换关系。随后按模块网格提取每个位置的明暗判定结果,经过纠错恢复和字符集解码后,还原为原始文本信息。

第四步:呈现结果。 将成功解码的信息展示给使用者,并提供便捷的复制功能,使其能够将信息用于后续操作。

设计原则

  • 本地优先:所有编码和解码运算均在用户设备本地完成,信息从生成到识别的全生命周期不离开用户设备,从根本上保障隐私安全。
  • 规则对称:编码与解码采用同一套公开的符号规则体系,确保任何符合该规则生成的图案都可以被同样遵循该规则的识读程序正确解析。
  • 即时反馈:编码操作应对输入变化做出即时响应,解码操作应在用户完成图像提交后尽快返回结果,减少等待带来的操作中断感。

本工具的数据编码与解码能力依赖于两个核心 npm 包,所有计算均在浏览器主线程中完成。


1. qrcode — 二维码生成

用途:将文本或 URL 编码为 QR 码 Data URL 图像,支持自定义尺寸、纠错级别和颜色。

npmhttps://www.npmjs.com/package/qrcode

GitHubhttps://github.com/soldair/node-qrcode

在本项目中的角色:接收用户输入的文本内容,根据设定的尺寸、纠错级别和颜色参数,生成可嵌入 <img> 标签的 Base64 Image Data URL。

核心调用代码(摘自 QrcodePage.vue):

qrCodeUrl.value = await QRCode.toDataURL(inputText.value, {
  width: qrSize.value,
  margin: 2,
  errorCorrectionLevel: errorLevel.value,
  color: {
    dark: foregroundColor.value,
    light: backgroundColor.value,
  },
})

设计说明toDataURL 方法异步执行编码运算,返回的 Data URL 可直接用于页面渲染或触发下载。margin 参数设为 2 个模块宽度,为码图四周保留必要的静区,确保识读设备能正确界定码图边界。errorCorrectionLevel 支持四级选项:L(约 7% 容损)、M(约 15%)、Q(约 25%)、H(约 30%)。color 参数允许独立设置码点色和背景色,但两者之间必须保持足够的对比度。

为提高响应性能,生成调用前加入了防抖控制(200ms 延迟),避免用户连续输入或快速拖动滑块时频繁触发编码运算:

function debounce<T extends (...args: unknown[]) => unknown>(fn: T, delay: number): T {
  let timer: ReturnType<typeof setTimeout> | null = null
  return ((...args: unknown[]) => {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }) as T
}

const debouncedGenerate = debounce(generateQrCode, 200)

watch([inputText, qrSize, errorLevel, foregroundColor, backgroundColor], () => {
  debouncedGenerate()
})

2. jsQR — 二维码识别

用途:从图像像素数据中检测并解码 QR 码,返回其中包含的文本内容。纯 JavaScript 实现,无需任何后端服务或浏览器扩展。

npmhttps://www.npmjs.com/package/jsqr

GitHubhttps://github.com/cozmo/jsQR

在本项目中的角色:接收从用户上传图片中提取的 Uint8ClampedArray 像素数据及图像宽高,通过定位图案检测和数据模块解析,还原出原始编码文本。

核心调用代码(摘自 QrcodePage.vue):

const img = new Image()
img.crossOrigin = 'Anonymous'

await new Promise<void>((resolve, reject) => {
  img.onload = () => resolve()
  img.onerror = () => reject(new Error('图片加载失败'))
  img.src = imageUrl
})

const canvas = document.createElement('canvas')
canvas.width = img.width
canvas.height = img.height
const ctx = canvas.getContext('2d')

if (!ctx) {
  throw new Error('无法创建画布上下文')
}

ctx.drawImage(img, 0, 0)
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
const code = jsQR(imageData.data, imageData.width, imageData.height)

if (code) {
  scanResult.value = code.data
} else {
  scanError.value = '未能识别到二维码,请确保图片清晰且包含有效的二维码。'
}

设计说明:识别流程在主线程同步执行。首先通过 Image 对象加载图片文件,设置 crossOrigin = 'Anonymous' 属性以防止跨域资源导致的画布污染问题。图片加载完成后,将其按原始尺寸绘制到一个离屏 Canvas 上,调用 getImageData 获取 RGBA 四通道像素数组。jsQR 接收三个参数:像素数据(Uint8ClampedArray,按行排列,每像素 4 字节依次为 R、G、B、A)、图像宽度(像素)和图像高度(像素)。内部流程为:先在像素阵列中搜索三个角的定位图案(Finder Pattern),确定码图边界与透视变换,再按模块网格读取明暗判定值,经过纠错和字符集解码后输出文本。识别成功时 code.data 为解码后的字符串;未检测到二维码时返回 null

重要说明:识别过程并未使用 Web Worker,所有图像处理和解码运算均在浏览器主线程同步执行。对于大尺寸图片,识别过程可能短暂阻塞用户界面。


数据流

生成方向:

用户输入文本
  -> 防抖 (200ms)
  -> QRCode.toDataURL()  [参数: width, margin, errorCorrectionLevel, color]
  -> Base64 Data URL
  -> <img> 元素渲染 / 下载为 PNG

识别方向:

用户选取图片文件
  -> FileReader.readAsDataURL()
  -> new Image() 加载
  -> Canvas 绘制 (drawImage)
  -> getImageData() 提取像素阵列 (Uint8ClampedArray + width + height)
  -> jsQR() 解码
  -> 文本结果 或 错误提示

二维码工具

生成和识别二维码的工具,支持自定义大小和纠错级别

生成二维码

200px

生成的二维码将显示在这里

识别二维码

点击或拖拽上传二维码图片

支持 JPG、PNG、GIF 格式

工具简介

本工具是一个在线二维码生成与识别工具。左侧面板用于将文字或网址生成为二维码图片并下载保存,右侧面板用于上传二维码图片并解码其中的内容。所有操作均在浏览器本地完成,数据不会上传到任何服务器。

支持的输入类型

生成模式:任意文本内容,最常用的场景是网址链接(URL)。

识别模式:JPG、PNG、GIF 格式的图片文件。支持点击上传区域选取文件,也支持将图片文件直接拖拽到上传区域。

操作步骤

生成二维码

  1. 在左侧「生成二维码」区域的文本框中输入您要编码的内容(例如一段文字、一个网址)。
  2. 拖动「二维码大小」滑块调整输出尺寸,可选范围为 100px 至 400px。
  3. 在「纠错级别」下拉框中选择合适的纠错能力:
    • L(低):约 7% 的码面损坏可恢复,码图最简洁。
    • M(中):约 15% 可恢复,日常使用推荐。
    • Q(较高):约 25% 可恢复,适合印刷张贴场景。
    • H(高):约 30% 可恢复,码图最密集,抗遮挡能力最强。
  4. (可选)点击前景色或背景色色块,自定义二维码的配色方案。请确保两色之间有足够的对比度,否则扫码设备可能无法正确识别。
  5. 二维码会根据您的输入实时生成并显示在预览区域。点击「下载二维码」按钮将二维码保存为 PNG 图片到本地。

识别二维码

  1. 在右侧「识别二维码」区域,点击虚线框内的上传区域选择图片,或直接将图片文件拖拽到该区域。
  2. 图片上传后将自动显示预览并开始识别,识别过程中会显示「正在识别...」的加载状态。
  3. 识别成功后,解码内容会显示在绿色提示框中。点击「复制结果」按钮可将内容复制到系统剪贴板。
  4. 如识别失败,红色提示框中会显示具体错误原因。常见原因包括:图片中未包含二维码、二维码不完整、图片过于模糊。

输入约束

  • 生成内容长度:建议控制在 1000 字符以内。内容越长,二维码中模块数量越多、排列越密集,对识读设备的分辨能力要求也越高。
  • 二维码尺寸:100px - 400px。如需打印后扫描,建议选择 200px 以上的尺寸以确保印刷后模块清晰可辨。
  • 识别图片格式:仅支持 JPG、PNG、GIF 三种格式。
  • 识别图片内容:图片必须包含完整、清晰的二维码图案。被裁剪、遮挡、严重透视变形或过度模糊的二维码无法被正确识别。

注意事项

  1. 对比度至关重要:生成二维码时,前景色与背景色之间的亮度差必须足够大。建议使用深色前景配浅色背景(如黑配白、深蓝配白),避免使用相近色调(如浅灰配白、深蓝配黑),否则识读设备将无法区分码点的明暗状态。
  2. 隐私安全保障:本工具纯前端运行,您输入的文字、生成的二维码、上传的图片均在本地处理,不会通过网络传输到任何远程服务器,请放心使用。
  3. 纠错级别的取舍:高纠错级别意味着更强的抗遮挡能力,但同时会导致码图更密集、生成图案更大。对于仅在屏幕上使用的二维码,M 级别已足够;对于需要打印、张贴在户外的二维码,建议选择 Q 或 H 级别。
  4. 识别图片的质量要求:识别时请使用正面拍摄、光照均匀、对焦清晰的二维码图片。斜拍角度过大或光线过暗/过曝都会显著降低识别成功率。如果识别失败,可以尝试裁剪图片使其仅包含二维码区域后重新上传。
  5. 浏览器兼容性:本工具依赖 Canvas API 进行图像处理。建议使用现代浏览器(Chrome 90+、Firefox 88+、Safari 14+、Edge 90+)。过于陈旧的浏览器版本可能不支持相关功能,导致识别功能无法正常使用。

中国各省访问量分布图

鼠标悬停查看各省份的访问数据统计

用户评论

所有评论均为匿名发布

1 浏览0 条评论
4TZk
暂无评论,来说两句吧