Skip to main content

qrref

Python package and reference implementation of the ISO/IEC 18004:2015 Standard for QR codes, with a simple but convenient CLI for showing, saving and copying generated QR codes.

Sample QR code

Purpose

This is first and foremost a reference implementation, meaning I wanted the code to be readable and well-documented, without lots of magic numbers and tables copied straight from the specification. For those wanting to implement their own QR code generator, or extending one to suit their needs (custom colors, styles, inset images, etc.) this should be a good basis.

Wherever possible, I've chosen to implement the table data as functions instead. This doesn't result in the shortest or fastest implementation, but should explain where the numbers come from better.

The priorities of this project have been as follows, in approximate order of importance.

  1. Referentiability. The code should adhere closely to the specification.
    • Most functions and tables are accompanied by comments referencing where they can be found in the specification. Look up "ISO/IEC 18004" and you can probably find it somewhere.
  2. Clarity. The code should be easy to read and understand.
    • Comments and docstrings are mandatory.
    • The code is split up into files with clearly different responsibilities, and should be understandable (mostly) on their own.
  3. Transparency. Table data should be generated by functions wherever possible.
    • The implementation could be made shorter by hard-coding certain parts, most notably the coefficients of the generating polynomials for the Solomon-Reed code. This is against the spirit of this project though.
    • Table data is still preferred where a function would be less clear.
  4. Efficiency. Looping over the entire symbol in Python should be avoided.
    • NumPy is used extensively to speed up generation.

Usage

Install by running

$ pip install qrref

or to also be able to copy QR codes directly to the clipboard, by running

$ pip install qrref[copy]

This is an optional dependency, since it uses pyperclipimg which states in its README: "This module is separate [from pyperclip] because it has some heavy dependencies (pywin32, Quartz, etc.)" Without it, you can still show and save QR codes as png.

You can then import qrref and use qrref.generate_qr_code in your own code, or use the command-line interface (CLI) directly.

Examples

Show a QR code with the message "This is a QR code". This is done using Matplotlib, which means that "F" toggles fullscreen and "Q" closes the window. Perfect for quickly throwing up a QR code on a big screen.

$ py -m qrref "This is a QR code"

Save the QR code to ./wikipedia_qr.png:

$ py -m qrref "https://wikipedia.org" --png --filename wikipedia_qr

Copy the QR code to the clipboard (requires installing with pip install qrref[copy]):

$ py -m qrref "https://wikipedia.org" --copy

To control the size of the saved/copied image, use -w/--width. The image will be upscaled (by an integer factor) to at least this big. Use -w 0 to get a pixel-perfect QR code.

$ py -m qrref "https://wikipedia.org" --copy -w 0

Run py -m qrref -h to see all arguments.

$ py -m qrref -h
usage: python.exe -m qrref [-h] [-L | -M | -Q | -H] [-v VERSION] [--png | --show | --copy] [-f FILENAME] [-w WIDTH] [-t] [-u] [--debug] [content]

Create a QR code and save, show or copy it.

positional arguments:
  content               What to encode in the QR code

options:
  -h, --help            show this help message and exit
  -v, --version VERSION
                        Which version (size) of QR code to use. By default, chooses the smallest one that the content fits in.
  -f, --filename FILENAME
                        Filename to save with
  -w, --width WIDTH     Minimum width of the image, in pixels
  -t, --transparent     Use transparent background
  -u, --utf-8           Use UTF-8 instead of Latin-1 encoding
  --debug               Show debug output

Error correction level:
  -L                    Low: 7 percent error correction
  -M                    Medium: 15 percent error correction (default)
  -Q                    Quartile: 25 percent error correction
  -H                    High: 30 percent error correction

How to save the QR code:
  --png                 As PNG
  --show                Show without saving (default)
  --copy                Copy image to clipboard

Reference details

The generation of a QR code is handled by qrref.qr.generate_qr_code. This function is fairly readable and illustrates the process from start to finish:

def generate_qr_code(
    content: str, 
    ec_level: Literal["L", "M", "Q", "H"], 
    version: int | None = None,
):
    if version is None:
        version, modes = select_version(content, ec_level)
    else:
        modes = select_modes(content, version)

    bitstream = encode_mixed(modes, version)
    bytestream = to_data_bytestream(bitstream, version, ec_level)
    blockstream = generate_error_correction_blocks(bytestream, version, ec_level)
    final_bytestream = interleave_blocks(blockstream, version, ec_level)

    symbol = place_bytestream(final_bytestream, version)
    insert_timing_patterns(symbol)
    insert_finder_patterns(symbol)
    insert_alignment_patterns(symbol, version)

    symbol, mask_pattern_id = apply_mask(symbol, version)

    place_format_bits(symbol, generate_format_bits(ec_level, mask_pattern_id))
    if version >= 7:
        place_version_bits(symbol, generate_version_bits(version))

    symbol = expand_quiet_region(symbol)
    return symbol

This uses functions split up over several files. Here's a high-level overview of what each file does, in the order they are used in the above function.

  1. qrref/data_analysis.py: Select the minimum version (qr code size) that the content (input string) fits in. Also select the encoding types that minimizes the length of the data bitstream (numeric data is denser than alphanumeric data, which is denser than byte data).
  2. qrref/data_encoding.py: Encode the message into a bitstream and group the bits together into bytes.
  3. qrref/error_correction.py: Generate error correction bytes using the Reed-Solomon codes. In practice, does this by finding polynomial remainders over the Galois Field of order 256 (wikipedia), which also uses qrref/galois_field.py. Turn the resulting data and error correction bytes into a bitstream by splitting them into blocks and interleaving those blocks. Also generate the format and version bits after the masking is complete.
  4. qrref/placement.py: Place the finalized bitstream into the symbol, as well as finder, alignment and timing patterns. After the format and version bits are generated, place those too.
  5. qrref/masking.py: Find and apply the mask that minimizes undesirable patterns, like long runs of the same color, etc. This is done after placing everything but the format and version bits in the symbol.

Auxiliary files:

  1. qrref/custom_types.py: Custom types for type hinting throughout the package.
  2. qrref/qr.py: Assemble and visualize the QR code.
  3. qrref/settings.py: Global settings. Currently only one, which is the encoding to use for byte strings (Latin-1 or UTF-8).
  4. qrref/table_data.py: Data from tables, either in the form of dictionaries or functions.

Metadata

Release files for qrref 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qrref 0.1.1
File Size Uploaded
qrref-0.1.1.tar.gz 27.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for qrref 0.1.1
File Interpreter ABI Platform
qrref-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 50.9 kB

Release files / qrref-0.1.1.tar.gz

Download URL qrref-0.1.1.tar.gz
Size 27.4 kB
Tags Source
SHA-256 checksum
How to use checksums
83c9298c3ef53915b14223a6811a9ae9d17d9447e3eb43a44df801cabc6289a4
BLAKE2b-256 checksum
How to use checksums
cab6acf1152ba4845568e01f3f36ed8d700b7590d0dc7219fcfe953e4ddb70ff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release files / qrref-0.1.1-py3-none-any.whl

Download URL qrref-0.1.1-py3-none-any.whl
Size 23.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
57dc1adfa2745bac4abb6423368e6ed978fa657fe786ce22e1958a20bfe379be
BLAKE2b-256 checksum
How to use checksums
8f4d267d0af378e2ac44bb7c5fd5b55ac164c1943023d55e04d40d3dbcdba6ab
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.0

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page