Mã Quick Response (QR), được tiêu chuẩn hóa quốc tế theo ISO/IEC 18004, đại diện cho một trong những hệ thống ký hiệu hai chiều bền bỉ và phổ biến nhất trong điện toán hiện đại. Được phát triển ban đầu vào năm 1994 bởi Masahiro Hara tại Denso Wave nhằm theo dõi các linh kiện ô tô trong dây chuyền lắp ráp, mã QR được thiết kế để đáp ứng hai yêu cầu khắt khe: khả năng nhận diện quang học nhanh chóng ở mọi góc quét đa hướng, cùng khả năng bảo toàn dữ liệu mạnh mẽ trước những hư hỏng vật lý nghiêm trọng, vết bẩn và rách nát.
Khác với mã vạch một chiều vốn chỉ mã hóa thông tin dọc theo một trục không gian nằm ngang duy nhất, mã QR hoạt động như một ma trận phẳng rời rạc gồm các phần tử vuông sáng và tối được gọi là "module". Tầng truyền tải dữ liệu nền tảng tích hợp đại số trừu tượng trường hữu hạn, cụ thể là mã sửa lỗi Reed-Solomon được tính toán trên trường Galois . Nền tảng đại số này cho phép bộ giải mã tái tạo dữ liệu bị mất, bị che khuất hoặc bị biến dạng mà không cần truyền lại.
Khi xây dựng các nền tảng web hiện đại, các kỹ sư thường xuyên cần các tiện ích để tạo mã QR chuẩn ISO trực tiếp cho các khóa bí mật xác thực, hồ sơ mạng hoặc trao đổi dữ liệu. Ngược lại, việc xác minh tải trọng ma trận và kiểm tra cấu trúc byte đòi hỏi các công cụ để giải mã QR client-side, đảm bảo dữ liệu nhạy cảm được giữ kín hoàn toàn trên thiết bị người dùng mà không bị truyền qua mạng bên ngoài.
1. Cấu trúc hình học của ma trận ISO/IEC 18004
Ma trận mã QR theo chuẩn ISO/IEC 18004 được cấu trúc trên một lưới tọa độ Descartes nghiêm ngặt. Kích thước vật lý dao động từ Version 1 ( module) lên đến Version 40 ( module). Mỗi phiên bản tiếp theo sẽ tăng kích thước lưới thêm đúng 4 module cho mỗi cạnh:
Trong đó biểu thị phiên bản ma trận.
Bề mặt ma trận được phân chia có hệ thống giữa các mẫu chức năng (giúp định vị hình học, đồng bộ hóa và hiệu chỉnh góc nhìn) cùng vùng mã hóa (chứa các codeword dữ liệu, byte chẵn lẻ sửa lỗi, thông tin định dạng và chỉ thị phiên bản).
+-----------------------------------------------------------------------+
| [FINDER 1] [TIMING HORIZONTAL] [FINDER 2] |
| 7x7 Pattern Alternating B/W 7x7 |
| Ratio 1:1:3:1:1 |
| |
| +---------+ +---------+ |
| | ### ### | | ### ### | |
| | # # | | # # | |
| | # ### # | FORMAT INFORMATION | # ### # | |
| | # ### # | (BCH Encoded Strip) | # ### # | |
| | # # | | # # | |
| | ### ### | | ### ### | |
| +---------+ +---------+ |
| [SEPARATOR] [SEPARATOR] |
| |
| [TIMING VERTICAL] [DATA & PARITY AREA] |
| Alternating B/W Interleaved Codewords |
| Upward/Downward 2-module tracks |
| Mask Pattern Applied |
| |
| +-----------+ |
| | ALIGNMENT | |
| | 5x5 Grid | |
| +-----------+ |
| +---------+ |
| | ### ### | |
| | # # | |
| | # ### # | |
| | # ### # | |
| | # # | |
| | ### ### | VERSION INFORMATION |
| +---------+ (Versions 7-40 only, 18-bit Golay) |
| [FINDER 3] |
+-----------------------------------------------------------------------+
QUIET ZONE (Minimum 4 Modules of Unmarked Light Space on all 4 Sides)Mẫu định vị (Finder Patterns) và tính bất biến affine
Đặc điểm trực quan dễ nhận biết nhất là ba Mẫu định vị (Position Detection Patterns) giống hệt nhau nằm ở các góc trên-trái, trên-phải và dưới-trái. Mỗi mẫu định vị bao gồm một khối vuông tối ở trung tâm, bao quanh bởi đường viền sáng rộng 1 module, và ngoài cùng là đường viền tối rộng 1 module, tạo thành cấu trúc .
Khi một đường quét cắt qua tâm của mẫu định vị ở bất kỳ góc định hướng nào (từ đến ), tỷ lệ độ rộng giữa các module đen và trắng luôn cho kết quả:
Tỷ lệ này là duy nhất về mặt toán học trong ma trận. Các bộ phát hiện cạnh trong thị giác máy tính quét tìm đặc trưng nhận dạng này để cô lập biên giới ma trận, tính toán các ma trận biến đổi affine, hiệu chỉnh độ nghiêng phối cảnh và xác định hướng xoay không gian của ký hiệu trong thời gian thực.
Các mẫu cấu trúc thứ cấp
- Vùng phân cách (Separators): Các đường viền sáng có độ rộng 1 module bao quanh mỗi mẫu định vị, ngăn không cho các module dữ liệu làm sai lệch tỷ lệ .
- Mẫu định thời (Timing Patterns): Nằm trên hàng 6 và cột 6 (chỉ số tính từ 0) nối liền giữa các mẫu định vị. Bao gồm các module tối và sáng xen kẽ, chúng xác lập tần số lấy mẫu vật lý và khoảng cách lưới tọa độ trên toàn bộ ma trận.
- Mẫu căn chỉnh (Alignment Patterns): Bắt buộc có từ Version 2 trở lên. Bao gồm một cấu trúc đồng tâm (một điểm tối ở tâm được bao quanh bởi một vòng sáng và đường viền tối ngoài cùng). Khi phiên bản tăng dần lên đến Version 40, một lưới gồm nhiều mẫu căn chỉnh sẽ bù trừ cho độ cong bề mặt vật lý (chẳng hạn như khi quét mã QR in trên vỏ lon hình trụ hoặc giấy bị nhăn).
- Vùng tĩnh (Quiet Zone): Một dải khoảng trắng không bị gián đoạn có độ rộng tối thiểu 4 module bao quanh toàn bộ ranh giới ngoài cùng, đảm bảo sự cô lập quang học khỏi các khối văn bản hoặc đồ họa liền kề.
2. Các chế độ mã hóa dữ liệu và đóng gói luồng bit
Các byte dữ liệu tải trọng không được ghi trực tiếp dưới dạng ASCII thô vào ma trận. Nhằm tối đa hóa mật độ lưu trữ trên các tập ký tự khác nhau, ISO/IEC 18004 định nghĩa nhiều chế độ mã hóa chuyên biệt.
| Chế độ mã hóa | Chỉ thị chế độ | Tập ký tự hỗ trợ | Số bit mỗi ký tự | Hiệu suất cải thiện so với 8-bit |
|---|---|---|---|---|
| Numeric | 0001 | Các chữ số từ 0 đến 9 | 3.33 bits/ký tự | Giảm ~58.3% |
| Alphanumeric | 0010 | 45 ký tự: 0-9, A-Z, khoảng trắng, $ % * + - . / : | 5.5 bits/ký tự | Giảm ~31.2% |
| Byte | 0100 | Luồng nhị phân toàn phần ISO-8859-1 hoặc UTF-8 | 8.0 bits/ký tự | Mức cơ sở |
| Kanji | 1000 | Ký tự Shift JIS | 13.0 bits/ký tự | Giảm ~18.7% so với 16-bit |
Cơ chế nén dữ liệu
Các chế độ Numeric và Alphanumeric đạt được mật độ bit phân số thông qua việc gom nhóm chuyển đổi cơ số:
- Nén Numeric: Chuỗi đầu vào được phân vùng thành các cụm 3 chữ số. Mỗi số nguyên 3 chữ số ( đến ) được mã hóa thành một giá trị nhị phân 10 bit (). Hai chữ số còn lại (nếu có) được mã hóa thành 7 bit (), và một chữ số đơn lẻ còn lại sẽ chiếm 4 bit.
- Nén Alphanumeric: Các ký tự được ghép thành từng cặp. Với các ký tự và được ánh xạ tới các giá trị trong bảng :
Vì , số nguyên thu được vừa vặn trong một từ 11 bit (), mang lại hiệu suất thực tế là bit cho mỗi ký tự.
Đóng khung và đệm luồng bit
Luồng bit liên tục được đóng khung tuần tự:
- Chỉ thị chế độ (Mode Indicator): Tiền tố 4 bit xác định chiến lược nén.
- Bộ đếm số lượng ký tự (Character Count Indicator): Độ dài trường được xác định bởi phiên bản ma trận và chế độ đang hoạt động (ví dụ, 8 bit cho chế độ Byte ở các Version 1-9; 16 bit ở các Version 10-40).
- Các bit dữ liệu: Tải trọng ký tự đã được nén.
- Ký tự kết thúc (Terminator): Một chuỗi bit chứa tối đa bốn số không (
0000) báo hiệu việc hoàn tất dữ liệu tải trọng. - Căn chỉnh byte: Các bit 0 được thêm vào cuối cho đến khi tổng độ dài luồng bit là bội số chính xác của 8.
- Đệm dung lượng (Capacity Padding): Nếu các byte đã gom lại chưa lấp đầy tổng dung lượng quy định cho phiên bản và cấp độ sửa lỗi đã chọn, bộ mã hóa sẽ liên tục xen kẽ giữa hai byte đệm tiêu chuẩn:
Chuỗi xen kẽ này duy trì sự cân bằng đồng đều giữa các module tối và sáng trên các khối lưu trữ chưa dùng, tránh tạo ra các vùng lớn không có biến đổi tín hiệu.
3. Số học trường Galois: và toán học đa thức
Động cơ toán học giúp mã QR tồn tại nguyên vẹn trước hư hỏng là mã sửa lỗi đại số Reed-Solomon. Reed-Solomon hoạt động trên các ký hiệu thay vì các bit riêng lẻ. Trong ISO/IEC 18004, mỗi ký hiệu đại diện cho một byte 8-bit.
Các phép toán số học truyền thống (cộng, nhân, chia) trên số thực hoặc số nguyên không bảo toàn phạm vi 8-bit hữu hạn mà không xảy ra tràn số hoặc mất độ chính xác. Để thực hiện các phép toán khép kín trên cấu trúc byte chính xác, mã QR sử dụng lý thuyết trường Galois, cụ thể là trường hữu hạn chứa phần tử: .
Xây dựng trường và đa thức nguyên thủy
Trong , các phần tử được biểu diễn dưới dạng đa thức có bậc tối đa là 7 với các hệ số nhị phân:
Khi nhân hai đa thức 8-bit, tích số có thể đạt tới bậc 14, vượt quá giới hạn của một byte 8-bit. Để duy trì tính khép kín, tích số được rút gọn theo modulo của một đa thức nguyên thủy bất khả quy không thể phân tích thành nhân tử trong trường. Chuẩn ISO/IEC 18004 định nghĩa là:
Trong hệ thập lục phân, đa thức này tương ứng với 0x11D (hoặc 285 ở hệ thập phân).
Các phép toán trên trường
- Phép cộng và phép trừ: Trong các trường hữu hạn có đặc số 2, phép cộng và phép trừ là như nhau và tương đương với phép toán XOR bit ():
Điểm mấu chốt là không có phép nhớ nào diễn ra qua ranh giới bit.
- Phép nhân qua bảng Log và Antilog: Phép nhân đa thức trực tiếp đi kèm rút gọn modulo với đòi hỏi chi phí tính toán rất lớn trong quá trình mã hóa thời gian thực. Thay vào đó, do có tính cyclic, mọi phần tử khác 0 trong trường đều có thể biểu diễn dưới dạng lũy thừa của một phần tử sinh nguyên thủy ().
Với hai phần tử bất kỳ khác 0 là và :
Bằng cách tính toán trước hai bảng tra cứu gồm 256 phần tử (một bảng lũy thừa/antilog expTable ánh xạ và một bảng logarit rời rạc logTable ánh xạ ), phép nhân được rút gọn thành các phép tra bảng với thời gian không đổi:
function gfMultiply(a: number, b: number, expTable: Uint8Array, logTable: Uint8Array): number {
if (a === 0 || b === 0) return 0;
const exponent = (logTable[a] + logTable[b]) % 255;
return expTable[exponent];
} GALOIS FIELD GF(2^8) MULTIPLICATION
Byte A ----------------> logTable[A] --------+
|
v
[ Integer Addition ]
[ Modulo 255 ]
|
v
Byte B ----------------> logTable[B] --------+----> expTable[Sum] ----> ProductThiết lập đa thức sinh
Để tạo ra byte chẵn lẻ sửa lỗi cho một khối dữ liệu nhất định, bộ mã hóa xây dựng một đa thức sinh . Các nghiệm của đa thức là các lũy thừa liên tiếp của phần tử trường nguyên thủy :
Ví dụ, việc tạo ra 2 byte sửa lỗi () đòi hỏi khai triển:
Vì và , ta có , suy ra:
Phép chia đa thức tổng hợp
Giả sử luồng dữ liệu gồm byte được biểu diễn dưới dạng đa thức thông điệp có bậc :
Đa thức thông điệp được dịch trái vị trí (nhân với ) để tạo khoảng trống cho các ký hiệu chẵn lẻ:
Trong đó là đa thức dư có bậc tối đa là . Các hệ số của đa thức dư này chính là các codeword chẵn lẻ Reed-Solomon chuẩn xác được nối tiếp vào luồng dữ liệu.
/**
* Computes Reed-Solomon parity codewords for a given data buffer over GF(2^8).
*/
export function computeReedSolomonParity(
data: Uint8Array,
parityCount: number,
expTable: Uint8Array,
logTable: Uint8Array,
generatorPoly: Uint8Array
): Uint8Array {
const remainder = new Uint8Array(parityCount);
for (let i = 0; i < data.length; i++) {
const factor = data[i] ^ remainder[0];
// Shift remainder register left
for (let j = 0; j < parityCount - 1; j++) {
remainder[j] = remainder[j + 1];
}
remainder[parityCount - 1] = 0;
if (factor !== 0) {
const logFactor = logTable[factor];
for (let j = 0; j < parityCount; j++) {
const genCoeff = generatorPoly[j];
if (genCoeff !== 0) {
const product = expTable[(logTable[genCoeff] + logFactor) % 255];
remainder[j] ^= product;
}
}
}
}
return remainder;
}4. Các cấp độ sửa lỗi và kỹ thuật xen kẽ khối Reed-Solomon
Chuẩn ISO/IEC 18004 quy định bốn cấp độ sửa lỗi (Error Correction Levels) khác nhau, cho phép các kỹ sư cân đối giữa mật độ thông tin và khả năng phục hồi vật lý.
| Cấp độ EC | Tỷ lệ byte chẵn lẻ | Dung lượng phục hồi xấp xỉ | Kịch bản triển khai điển hình |
|---|---|---|---|
| Cấp L (Low) | ~7% tổng số codeword | ~7% số ký hiệu bị hỏng | Màn hình hiển thị độ nét cao, sạch sẽ, màn hình di động |
| Cấp M (Medium) | ~15% tổng số codeword | ~15% số ký hiệu bị hỏng | Mặc định cho tem nhãn công nghiệp thông dụng |
| Cấp Q (Quartile) | ~25% tổng số codeword | ~25% số ký hiệu bị hỏng | Môi trường dễ bị mài mòn mạnh hoặc bám bẩn |
| Cấp H (High) | ~30% tổng số codeword | ~30% số ký hiệu bị hỏng | Thẻ đeo có chèn logo trung tâm hoặc tác phẩm đồ họa |
Giới hạn phục hồi lỗi theo toán học
Mã Reed-Solomon thuộc nhóm mã phân tách khoảng cách tối đa (Maximum Distance Separable - MDS), đạt được giới hạn singleton tối ưu về mặt lý thuyết. Đối với mã MDS có ký hiệu chẵn lẻ:
Trong đó:
- đại diện cho số lỗi ký hiệu chưa biết (cả vị trí lỗi lẫn giá trị lỗi đều không biết trước).
- đại diện cho số ký hiệu bị xóa đã biết (vị trí lỗi được xác định qua thị giác do vết xước hoặc vật cản, nhưng giá trị đã mất).
Do đó, ký hiệu chẵn lẻ có thể sửa được tối đa:
- lỗi ngẫu nhiên, HOẶC
- điểm xóa đã biết, HOẶC
- Bất kỳ tổ hợp tuyến tính trung gian nào thỏa mãn .
Kiến trúc xen kẽ khối (Block Interleaving)
Trong ma trận Version 2 trở lên, dữ liệu hiếm khi được xử lý như một khối đơn nhất. Hư hỏng vật lý thường xuất hiện dưới dạng các vết trầy xước hoặc vết bẩn trải dài trong không gian, gây ra các chuỗi lỗi liên tiếp (burst errors). Nếu một khối Reed-Solomon đơn lẻ phải chịu một vết rách liên tục dài 30 byte, ngưỡng phục hồi của khối đó sẽ bị vượt quá, khiến toàn bộ mã không thể đọc được.
Để khắc phục điều này, tiêu chuẩn phân chia dữ liệu thành các khối Nhóm 1 và Nhóm 2, tạo các byte chẵn lẻ độc lập, sau đó sắp xếp xen kẽ có hệ thống cả byte dữ liệu lẫn byte chẵn lẻ trên bố cục vật lý.
Original Data Stream: [ D1, D2, D3, D4, D5, D6, D7, D8 ]
Partitioned into 2 Blocks:
Block A: [ D1, D3, D5, D7 ] --> Parity A: [ PA1, PA2 ]
Block B: [ D2, D4, D6, D8 ] --> Parity B: [ PB1, PB2 ]
INTERLEAVED PHYSICAL TRANSMISSION SEQUENCE:
Data Codewords: [ D1, D2, D3, D4, D5, D6, D7, D8 ]
Parity Codewords: [ PA1, PB1, PA2, PB2 ]Khi một vết xước quang học phá hủy bốn byte liên tiếp trên nhãn in (ví dụ: phá hủy các byte tại chỉ số truyền tải từ 2 đến 5: ), kỹ thuật xen kẽ đảm bảo rằng Khối A và Khối B mỗi khối chỉ chịu hai ký hiệu bị hỏng. Nhờ mỗi khối sở hữu nhiều từ chẵn lẻ, cả hai khối đều được phục hồi thành công.
5. Bố trí ma trận, phương pháp lọc mặt nạ và kết xuất trên trình duyệt
Sau khi luồng bit xen kẽ được lắp ráp, các codeword sẽ được ánh xạ vào lưới ma trận vật lý. Quá trình bố trí bắt đầu từ góc dưới cùng bên phải và tiến lên trên theo các cột rộng 2 module. Khi chạm đến đường biên trên cùng, dải module sẽ dịch sang trái hai module và tiếp tục đi xuống, bỏ qua các mẫu chức năng đã dành riêng (mẫu định vị, mẫu định thời và mẫu căn chỉnh).
Module Placement Vector (Zigzag 2-Column Track)
^ | [Col 20] [Col 19] |
| | (6) (5) | Upward Phase
| | (4) (3) |
| | (2) (1) |
| +-------------------+
| Steps left 2 columns, reverses direction
| +-------------------+
v | (7) (8) | Downward Phase
| (9) (10) |Sự nhầm lẫn quang học và các mẫu mặt nạ (Masking Patterns)
Nếu dữ liệu thô chứa các chuỗi bit giống nhau kéo dài (chẳng hạn như các số 0 lặp lại từ phần đệm), ma trận vật lý sẽ xuất hiện các dải lớn toàn module đen hoặc trắng. Các vùng rộng không có sự biến đổi sẽ làm mất ổn định cơ chế kiểm soát độ lợi của cảm biến quang học và tạo cảm giác giả mạo mẫu định vị, gây nhầm lẫn cho logic xác định hướng của bộ giải mã.
Để đảm bảo entropy quang học đồng đều, toàn bộ vùng mã hóa được phủ mặt nạ XOR với một trong tám hàm lưới nhị phân tiêu chuẩn:
| Mẫu mặt nạ | Điều kiện thuật toán () |
|---|---|
000 | |
001 | |
010 | |
011 | |
100 | |
101 | |
110 | |
111 |
Mô hình tính điểm phạt theo ISO/IEC 18004
Bộ mã hóa tạo ra tám ma trận ứng viên bằng cách áp dụng tuần tự từng mẫu mặt nạ. Mỗi ma trận ứng viên được đánh giá dựa trên bốn công thức tính điểm phạt nghiêm ngặt (từ đến ):
- Điểm phạt (Các module giống nhau liền kề): Phạt các chuỗi từ 5 module trở lên có cùng màu liên tiếp trên bất kỳ hàng hoặc cột nào. Điểm số: điểm cho một chuỗi có độ dài .
- Điểm phạt (Các cụm khối): Quét tìm các khối module có màu đồng nhất. Điểm số: cho một khối .
- Điểm phạt (Giả mạo mẫu định vị): Quét tìm sự xuất hiện của chuỗi mẫu tối-sáng
10111010000hoặc00001011101trên bất kỳ hàng hoặc cột nào. Điểm số: 40 điểm cho mỗi lần xuất hiện. - Điểm phạt (Mất cân bằng tỷ lệ sáng/tối): Tính toán phần trăm tổng số module tối . Đánh giá độ lệch so với phân bố lý tưởng 50%:
Ma trận ứng viên có tổng điểm thấp nhất () sẽ được chọn làm mẫu sản xuất tối ưu. Chỉ số mặt nạ 3-bit và cấp độ sửa lỗi 2-bit được mã hóa cùng nhau thành một chuỗi 15-bit được bảo vệ bởi mã Bose-Chaudhuri-Hocquenghem (BCH) , được phủ mặt nạ XOR với 101010000010010, và ghi liền kề với các mẫu định vị.
Kết xuất ma trận phía client-side
Quy trình làm việc truyền thống của các kỹ sư thường sử dụng các endpoint kết xuất trên đám mây để chuyển đổi chuỗi ký tự thành hình ảnh mã vạch. Tuy nhiên, việc truyền các khóa xác thực nội bộ, địa chỉ thiết bị mạng hoặc thông tin đăng nhập nhạy cảm qua các kết nối HTTP từ xa sẽ khiến dữ liệu quan trọng đối mặt với nguy cơ bị ghi log trung gian, lưu bộ nhớ đệm proxy và đánh chặn.
PetexSpace giải quyết vấn đề này thông qua việc thực thi hoàn toàn trong trình duyệt. Toàn bộ chu trình xử lý, từ việc tách token chuỗi UTF-8 và chia đa thức trường Galois cho đến đánh giá điểm phạt và rasterize lên canvas, đều chạy bằng TypeScript thuần túy bên trong sandbox của trình duyệt. Tận dụng ngữ cảnh HTML5 Canvas 2D tiêu chuẩn hoặc đồ họa véc-tơ Scalable Vector Graphics (SVG) có tính khai báo, quá trình kết xuất mã vạch diễn ra với tốc độ thực thi máy gốc và đảm bảo tuyệt đối không có dữ liệu đo từ xa nào gửi qua mạng.