Cách tạo mã QR từng bước
(nayuki.io)- Theo dõi quá trình nội bộ khi văn bản được chuyển thành mã QR qua phần trực quan hóa từ bước 0 đến 9, có thể xem nguyên lý hoạt động của thư viện Nayuki QR Code generator
- Chuỗi nhập ví dụ
Hello, world! 123được phân tích thành 17 code point Unicode và được mã hóa ở chế độ Byte, không phải Numeric, Alphanumeric hay Kanji - Sau khi nối các bit chế độ, số ký tự, dữ liệu segment và bit kết thúc, tạo ra 19 codeword dữ liệu, vừa khớp với dung lượng ECC L của Version 1
- Mã QR Version 1 gắn 19 codeword dữ liệu và 7 codeword ECC Reed–Solomon vào 1 khối, rồi bố trí các mẫu cố định và module dữ liệu
- So sánh penalty của 8 mask và chọn Mask pattern 3 có tổng điểm thấp nhất; kết quả cuối cùng không chỉ là mã hóa đơn thuần mà còn được quyết định sau bước đánh giá chất lượng
Mục đích của demo và xử lý đầu vào
- Ứng dụng web này trực quan hóa từng bước quá trình một chuỗi văn bản được mã hóa thành mã QR
- Trang này diễn giải quá trình mã hóa để có thể hiểu hoạt động nội bộ của QR Code generator library
- Các mục nhập của người dùng gồm chuỗi văn bản, mức sửa lỗi, ép Version tối thiểu và ép mẫu mask
Bước 0: Phân tích ký tự Unicode
- Chuỗi ví dụ là
Hello, world! 123, và số code point của văn bản nhập là 17 - Mỗi ký tự được kiểm tra xem có thể mã hóa trong các chế độ Numeric, Alphanumeric, Byte, Kanji hay không
- Khả năng mã hóa của toàn bộ chuỗi theo từng chế độ như sau
- Numeric: không thể
- Alphanumeric: không thể
- Byte: có thể
- Kanji: không thể
- Chế độ segment được chọn để chứa toàn bộ ký tự là Byte
Bước 1: Tạo segment dữ liệu
- Mỗi ký tự được chuyển thành chuỗi bit
- Ở chế độ Numeric và Alphanumeric, các ký tự liên tiếp được gom lại để mã hóa
- Ở chế độ Byte, một ký tự tạo ra một trong các độ dài 8, 16, 24, 32 bit
- Trong ví dụ, giá trị thập lục phân của từng ký tự được chuyển thành 8 bit
H:48→01001000e:65→011001011:31→001100012:32→001100103:33→00110011
- Chương trình demo luôn tạo một segment duy nhất để đơn giản hóa
- Cách phân tách tối ưu nhằm giảm tổng độ dài bit được trình bày riêng trong optimal text segmentation for QR codes
Bước 2: Khớp số Version
- Tổng độ dài bit cần thiết để biểu diễn danh sách segment thay đổi theo phạm vi Version
- Version 1~9: 148 bit, 19 codeword
- Version 10~26: 156 bit, 20 codeword
- Version 27~40: 156 bit, 20 codeword
- Codeword được định nghĩa là 8 bit, tức 1 byte
- Dung lượng codeword dữ liệu của mã QR thay đổi theo Version và mức sửa lỗi
- Đầu vào ví dụ vừa khớp với Version 1 ở mức sửa lỗi đã chọn
- Số Version cuối cùng được chọn là 1
Bước 3: Nối segment, padding và tạo codeword
- Nối nhiều chuỗi bit lại để tạo chuỗi bit dữ liệu
- Segment 0 mode:
0100, 4 bit - Segment 0 count:
00010001, 8 bit - Segment 0 data: 136 bit
- Terminator:
0000, 4 bit
- Segment 0 mode:
- Tổng số bit tích lũy là 152 bit
- Trong ví dụ, cả bit padding và byte padding đều là 0 bit
- Toàn bộ byte codeword dữ liệu được chia theo đơn vị 8 bit và hiển thị ở dạng thập lục phân
41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30
Bước 4: Chia khối, thêm ECC và interleave
- Thống kê khối của ví dụ như sau
- Số codeword dữ liệu: 19
- Số khối: 1
- Codeword dữ liệu trên mỗi khối ngắn: 19
- Codeword dữ liệu trên mỗi khối dài: không áp dụng
- Codeword ECC trên mỗi khối: 7
- Số khối ngắn: 1
- Số khối dài: 0
- Chuỗi codeword dữ liệu được chia thành khối ngắn và khối dài, rồi tính và gắn codeword ECC vào cuối mỗi khối
- Quá trình toán học để tính mã sửa lỗi Reed–Solomon bị lược bỏ vì dài, tẻ nhạt và không thú vị
- Chuỗi codeword cuối cùng được cấu thành bằng cách interleave codeword dữ liệu và ECC
41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30 85 A9 5E 07 0A 36 C9
- Chuỗi bit cuối cùng sẽ được vẽ theo quét zigzag cũng được tạo từ chuỗi codeword này
Bước 5~6: Bố trí mẫu cố định và codeword
- Ở bước mẫu cố định, vẽ timing pattern tại hàng 6 và cột 6
- Ở ba góc, đặt finder pattern 8×8 bao gồm cả separator
- Quanh finder có các dummy format bits tạm thời
- Ở bước bố trí codeword, tính quét zigzag bắt đầu từ góc dưới bên phải
- Quét zigzag bỏ qua các module chức năng (function module) và đi qua các module chưa được điền
- Các module dữ liệu, ECC và remainder được vẽ theo giá trị bit của codeword cuối cùng và thứ tự zigzag
- Ví dụ, codeword thập lục phân
C5là nhị phân11000101, tạo ra chuỗi module[dark, dark, light, light, light, dark, light, dark]
Bước 7~9: Áp dụng mask và tính penalty
- Mỗi mẫu mask chỉ ảnh hưởng đến các module không phải chức năng (non-function module)
- Mask được áp dụng cho các module dữ liệu, ECC và remainder bằng phép XOR
- Format bits thực tế được vẽ quanh finder
- Quá trình tìm penalty kiểm tra các yếu tố sau
- Run ngang có từ 5 module cùng màu trở lên liên tiếp
- Run dọc có từ 5 module cùng màu trở lên liên tiếp
- Box 2×2 cùng màu
- Mẫu ngang giống finder
- Mẫu dọc giống finder
- Cân bằng giữa module tối và module sáng
- Kích thước và tỷ lệ màu của mã QR ví dụ như sau
- Độ dài một cạnh: 21
- Tổng số module: 441
- Module sáng: 221
- Module tối: 220
- Tỷ lệ module tối: 49.887%
- Độ lệch so với một nửa: −0.113%
- Tổng penalty của 8 mask như sau
- Mask 0: 1204
- Mask 1: 1134
- Mask 2: 1084
- Mask 3: 1081
- Mask 4: 1121
- Mask 5: 1100
- Mask 6: 1189
- Mask 7: 1137
- Mask có tổng penalty thấp nhất là Mask pattern 3
Mã nguồn
- Mã nguồn TypeScript của ứng dụng web được cung cấp dưới dạng file 0, file 1
- Có thể xem mã JavaScript đã biên dịch tại creating-qr-code-steps.js
1 bình luận
Ý kiến trên Hacker News
Ở đây tác giả cũng nói nó “dài, chán và không mấy thú vị”, nhưng vì ai cũng nghĩ vậy nên giờ tìm nội dung này khá khó
Reed-Solomon được học sau khoảng hơn nửa học kỳ một chút, và cốt lõi là nó dựa trên đa thức. Nếu có đủ điểm thì đa thức được xác định chính xác, nên nếu thêm các điểm dư thừa, ta có thể khôi phục ngay cả khi một số điểm biến mất
Phần còn lại là cách áp dụng điều đó vào dữ liệu nhị phân, tức là phần dùng trường hữu hạn; nó đẹp về mặt toán học nhưng trở nên khá phức tạp
https://www.thonky.com/qr-code-tutorial/error-correction-cod...
https://dev.to/maxart2501/let-s-develop-a-qr-code-generator-...
https://www.youtube.com/watch?v=w5ebcowAJD8
Tôi cảm nhận rõ không khí tinh hoa chủ nghĩa trong các bình luận. Lướt qua blog thì thấy tác giả xin quyên góp Bitcoin và đề xuất $3, nhưng có vẻ không tính đến việc một phần đáng kể có thể mất vào phí giao dịch
Cảm giác như: “Không, bạn không được dùng mã trong kho GitHub của tôi cho chatbot dự án đại học của bạn. Tiêu chuẩn lập trình của bạn không đạt tiêu chuẩn của tôi. Và tiếng Anh của bạn cũng tệ nữa”
May là tác giả cũng chia sẻ riêng những phản hồi tốt: https://www.nayuki.io/page/decent-feedback-from-readers
Tôi không muốn kiểu “chỉ cần gắn thư viện computer vision này vào rồi đưa ảnh vào là có kết quả” như thấy trên Google
Tôi đang tìm một hướng dẫn giả định rằng đã có dữ liệu ảnh thô đã được giải mã, rồi triển khai tất cả các thuật toán cần thiết
Tôi cũng tìm thấy vài cái trên GitHub nhưng có vấn đề khác, nên đã tự tạo nhanh bằng một thư viện được thiết kế tốt mà trước đây từng dùng, mất khoảng 15 phút
https://greggman.github.io/qr-code/
Có thể thêm nhiều tùy chọn hơn, nhưng thật ra tôi nghĩ đa số người dùng không cần những tùy chọn đó
Nếu có tài liệu hữu ích nào về phần sửa lỗi liên quan đến mã QR thì tôi muốn biết
https://github.com/aabiji/qr
https://github.com/PDP-10/its/blob/master/src/lars/qrcode.8