4 Nov 2026On another page on this site you can see how QR codes get encoded, this page is about the opposite process of decoding the matrix from captured image back to a string. The method shown here illustrates a possible algorithm, but real software for this purpose may work differently. The QR code above is shown neat and tidy, but in reality the camera captures the code in a rotated, tilted shape, with uneven pixel spacing and possibly blurred.
Click on the icon below the code to generate a new, random QR code for use on this page. The version number of the code determines its size in pixels. We are limiting the codes of this page to small versions for better visibility, but the QR specification allows for larger matrices too. Try scanning the QR code to naviagte to this page!
Here we have a version of the same code as if it were captured at an angle by a camera, close up. The task of the QR decoding algorithm is to convert this image into a bit string and recover the encoded text from it.
The first steps in processing the QR code are to undo the action of the camera, by rotating the code into upright position and removing any tilt from the image. For this, the algorithm has to first identify the three corner markings, which are highlighted with the red crosses. The missing fourth corner marker indicates the rotational position. Click play to start the animation.
Once these steps are completed the pixels, called modules here, have to be identified by their position between the markers and along the so-called timing lines.
This animation shows the steps starting with the rectified matrix image on the left, all the way to a raw string on bits, shown on the right side. The so-called timing patterns, lines of on-off pixels between the corners, highlighted in green here, help estimate the distance between neighbouring pixels. With this information, the algorithm is ready to translate the captured image into a field of bits. Blue bits carry formatting information, normal bits are in black.
At the end the algorithm decodes the formatting bits to obtain the error correction level and the mask number.
When the code was made, a mask pattern was laid over the data bits to avoid large uniform areas and patterns that could be confused with the finder patterns. The mask number decoded from the formatting bits tells which of the eight patterns was used. Shown on the right in grey and white beneath the data bits, the mask is removed by flipping every bit on a grey square, row by row. The formatting bits are not masked this way and are left out.
With the mask removed, the bits are taken out of the code eight at a time, one codeword after the other, and lined up as a plain bit stream on the right. The codewords are not placed in the code in the order of the stream: they start in the bottom right corner and wind upwards and downwards in two-module wide columns, and for larger codes the codewords of several blocks are interleaved. The bits of the stream are coloured by their meaning: black bits carry the message, green bits are meta information such as the mode indicator, the character count, the terminator and padding, and dark red bits are for error correction. Grey bits on the left are remainder bits that belong to no codeword.
What remains are the black message bits of the data stream, eight to a byte. The mode indicator told us that the bytes are in byte mode, which holds text as UTF-8, so the bytes are turned back into characters one after the other. Most characters of a web address take a single byte, others take more. At the end the URL of this page that was encoded on the first panel appears again.
The Claude Opus LLM helped create this page. There are more algorithms and data structures to be found on the main page.
Please consider sharing this site on social media!