Creating a QR Code step by step
This JavaScript demo application visualizes in detailed steps, how a text string is encoded into a QR Code barcode symbol. The content of this page essentially explains and justifies how my QR Code generator library works internally.
User input
QR Code output
Step-by-step process
Show/hide each step:
0. Analyze Unicode characters
Number of code points in the input text string:
Details of each character:
Index | Char | CP hex | NM | AM | BM | KM |
---|
Can every character be encoded in:
Mode | Encodable |
---|
Chosen segment mode to encode all characters:
1. Create data segment
Convert each character to bits. For numeric and alphanumeric modes, consecutive characters are grouped together before being encoded into bits. For byte mode, a character produces either 8, 16, 24, or 32 bits.
Index | Char | Values (hex) | Value | Combined | Bits |
---|
The created single segment:
- Mode:
- Count:
- Data:
(This demo program always creates a single segment for simplicity. But it is possible to segment the text optimally to minimize the total bit length.)
2. Fit to version number
Total bit length needed to represent the list of segments, depending on version:
Range | Num bits | Num codewords |
---|---|---|
Version 1 ~ 9 | ||
Version 10 ~ 26 | ||
Version 27 ~ 40 |
(Note: A codeword is defined as 8 bits, also known as a byte.)
QR Code capacity of data codewords per version and error correction level, and whether the data fits (green/red background):
Version | ECC L | ECC M | ECC Q | ECC H |
---|
Chosen version number:
3. Concatenate segments, add padding, make codewords
Join a variety of bit strings together:
Item | Bit data | Num bits | Sum bits |
---|
Notes:
The segment mode is always a 4-bit field.
The character count’s field width depends on the mode and version.
The terminator is normally four “0” bits, but fewer if the data codeword capacity is reached.
The bit padding is between zero to seven “0” bits, to fill all unused bits in the last byte.
The byte padding consists of alternating (hexadecimal) EC and 11 until the capacity is reached.
The entire sequence of data bits:
The entire sequence of data codeword bytes (by splitting the bit string into groups of 8 bits), displayed in hexadecimal:
4. Split blocks, add ECC, interleave
Statistics about all blocks:
Number of data codewords: | |
Number of blocks: | |
Data codewords per short block: | |
Data codewords per long block: | |
ECC codewords per any block: | |
Number of short blocks: | |
Number of long blocks: |
Split the sequence of data codewords (green background) into short and long blocks; then for each block, compute the ECC codewords (blue) and append them to the end of the block:
Block index |
---|
(Note: The math behind computing the Reed–Solomon error correction codes is omitted because it is long, tedious, and not very interesting.)
The final sequence of codewords formed by interleaving data/ECC codewords from different blocks:
The final sequence of bits to draw in the zigzag scan:
5. Draw fixed patterns
Draw the horizontal and vertical timing patterns (on both row 6 and column 6, counting from 0 starting at the top left corner):
Draw finder patterns on the three corners, each of which is 8×8 including the separator, overwriting some timing modules:
Draw the grid of alignment patterns, each of which is 5×5, but skipping the three finder corners, and ones that overlap timing modules blend in perfectly:
Draw temporary dummy format bits (adjacent to the finders):
Draw the two 6×3 version information blocks (adjacent to the finders):
6. Draw codewords and remainder
Compute the zigzag scan (which starts from the bottom right corner) to visit all unfilled modules (i.e. skipping function modules):
Draw data/ECC modules according to the zigzag scan order and bit values from the final sequence of codewords:
(For example, the codeword byte C5 (hex) is 11000101 in binary, and produces the sequence of modules [dark, dark, light, light, light, dark, light, dark].)
7. Try applying each mask
Show:
The mask pattern (only affects non-function modules):
XOR the mask to the modules of data, ECC, and remainder:
Draw the actual format bits (adjacent to the finders):
8. Find penalty patterns
Horizontal runs of same color modules (each at least 5 long):
Vertical runs of same color modules (each at least 5 long):
2×2 boxes of same color modules:
Horizontal finder-like patterns:
Vertical finder-like patterns:
Balance of dark/light modules:
Side length: | |
Total modules: | |
Light modules: | |
Dark modules: | |
Proportion dark: | |
Deviation from half: |
9. Calculate penalty points, select best mask
Mask | RunP | BoxP | FindP | BalP | TotalP |
---|
Lowest total penalty points: Mask pattern
How penalties are calculated:
RunP: 3 points for each 5-module linear run of the same color, 4 points for each 6-module run, 5 points for each 7-module run, 6 points for each 8-module run, etc. Runs cannot overlap.
BoxP: 3 points for each 2×2 box of the same color. Boxes can overlap.
FindP: 40 points for each finder-like pattern. Finder patterns can overlap.
BalP: 0 points if the proportion of dark modules is in the range [45%, 55%]; 10 points if within [40%, 60%]; 20 points if within [35%, 65%]; 30 points if within [30%, 70%]; etc.
This web application’s source TypeScript code (file 0, file 1) and compiled JavaScript code are available for viewing.
More info
- Wikipedia: QR code - Design
- Thonky.com: QR Code Tutorial
- YouTube: James Explains - How QR Codes Are Built
- research!rsc (Russ Cox): QArt Codes
- QRazyBox - QR Code Analysis and Recovery Toolkit (live app)
- Piko & blinry: Reading QR codes without a computer!
- YouTube: Pillazo - How to Decode a QR Code by Hand
- YouTube: Veritasium - I used to hate QR codes. But they're actually genius
- YouTube: The 8 Bit Theory - The C128, VIC-20, C64, Mega65, and Commander X16 generate QR Codes. In Basic, C and 6502 Assembly