> For the complete documentation index, see [llms.txt](https://infinitode-docs.gitbook.io/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://infinitode-docs.gitbook.io/documentation/package-documentation/qrforge-package-documentation/qrforge-usage-examples.md).

# qrforge Usage Examples

Runnable qrforge examples: gradients, module shapes, shaders, logos, textures, backgrounds, presets, every output format, the CLI and batch generation.

These examples are complete recipes you can copy into a script or notebook. Every one of them works with the default install (`pip install qrforge`); steps that need Pillow are marked.

Looking for pictures instead of code? The [qrforge Gallery](/documentation/package-documentation/qrforge-package-documentation/qrforge-gallery.md) shows what each preset and feature actually renders to.

```python
import qrforge
```

***

## 1. Your first QR code

Save a styled symbol in one line, then render the same data into as many formats as you need.

```python
import qrforge

# one-shot: data, path, preset
qrforge.save("https://example.com", "code.png", "neon", scale=12)

# or keep a QR object so you can reuse it
qr = qrforge.QR("https://example.com", ec="h")
qr.save("code.png", scale=12)
qr.save("code.svg")            # vector
qr.save("code.pdf")            # print-ready vector
print(qr.terminal())           # render in the terminal
```

`scale` is pixels per module for raster output; the default is `8`. `ec` is the error correction level (`"l"`, `"m"`, `"q"`, `"h"`) and defaults to `"m"`.

***

## 2. Encoding options

`QR` encodes lazily: the matrix is built the first time you render, ask for `qr.matrix`, or call `qr.info()`.

```python
import qrforge

qr = qrforge.QR("https://example.com", ec="h")   # L / M / Q / H
print(qr.info())
# {'data': 'https://example.com', 'version': 3, 'level': 'H', 'mask': 3,
#  'size': 29, 'modules': 841, 'codewords': 70, 'dark_ratio': 0.5184,
#  'penalty': 1280, 'segments': [('byte', 19)]}

# force a version and a mask (useful for fixed-size layouts)
qr = qrforge.QR("hello", ec="q", version=5, mask=2)

# pick the encoding mode instead of letting qrforge choose automatically
qrforge.QR("0123456789", mode="numeric").info()["segments"]   # [('numeric', 10)]
qrforge.QR("HELLO WORLD", mode="alnum").info()["segments"]    # [('alnum', 11)]

# change the payload of an existing object
qr = qrforge.QR("hello")
qr.encode("world")
qr.verify()          # 'world'
qr.size              # 21 modules
```

{% hint style="info" %}
`version` is 1–40 and `mask` is 0–7. Both are chosen automatically when omitted. If the payload does not fit, qrforge raises `qrforge.DataTooLong`.
{% endhint %}

***

## 3. Colours and gradients

A colour can be a hex string, `rgb()` / `hsl()` function string, CSS colour name, tuple, or `qrforge.Color`. A list of colours becomes a linear gradient; a dict controls the gradient type and geometry.

```python
import qrforge

qr = qrforge.QR("gradient demo", ec="h")

# linear gradient (list shorthand)
qr.use_style(fg=["#ff9a3c", "#ff4d6d", "#7b2ff7"])

# linear gradient with an angle and explicit stop positions
qr.use_style(fg={"kind": "linear", "angle": 45,
                 "colors": [(0.0, "#000000"), (0.6, "#00ff88"), (1.0, "#ffffff")]})

# radial and conic gradients
qr.use_style(fg={"kind": "radial", "colors": ["#ffffff", "#1f6feb"],
                 "center": (0.5, 0.35), "radius": 0.8})
qr.use_style(fg={"kind": "conic", "start_angle": 90,
                 "colors": ["#ff71ce", "#01cdfe", "#05ffa1"]})

# transparent background, and separate colours for the eyes / function modules
qr.use_style(bg=None, eye_fg="#00ff88", function_fg="#0077ff")

# CSS names and functional notation work anywhere a colour is accepted
qr.use_style(fg="tomato", bg="hsl(210, 100%, 12%)")

qr.save("gradient.png", scale=12)
```

***

## 4. Module shapes

Shapes are addressed by name (or alias). Pass a list to mix shapes randomly per module, and use `seed` for reproducible randomness.

```python
import qrforge

qr = qrforge.QR("shapes", ec="h")

# one shape for every module
qr.use_style(module_shape="hexagon", module_scale=0.9, module_gap=0.05)

# random mix of shapes, with per-module jitter
qr.use_style(module_shape=["dot", "star", "hexagon", "leaf"],
             module_scale=0.92, module_rotation=15,
             module_jitter=0.2, seed=3)

# eyes (finder patterns) can use their own shape, ring width and size
qr.use_style(eye_shape="rounded", eye_dot_shape="circle",
             eye_ring=1.1, eye_scale=0.95, eye_dot_scale=1.1)

# draw timing/format modules with a different shape (it can differ from data modules)
qr.use_style(module_shape="dot", function_shape="bar_h")

qr.save("shapes.svg")
```

Register a custom shape as a signed distance field in module units (a module spans `-0.5 .. 0.5`):

```python
import math
import qrforge

@qrforge.shape("wave")
def wave(x, y, radius=0.0):
    return qrforge.shapes.sd_circle(x, y + 0.08 * math.sin(x * 9), 0.5)

qr = qrforge.QR("custom shape").use_style(module_shape="wave")
qr.save("wave.png", scale=12)
print(qr.verify())     # the symbol still decodes
```

`qrforge.shapes.names()` lists the built-in shapes and `qrforge.shapes.get("dots")` looks one up (aliases included). See [Shapes & Shaders](/documentation/package-documentation/qrforge-package-documentation/qrforge-reference/qrforge-shapes-and-shaders.md) for the full list.

***

## 5. Eyes (finder patterns)

The three finder patterns are styled independently from the data modules.

```python
import qrforge

qr = qrforge.QR("eyes", ec="h")
qr.use_style(
    module_shape="dot", module_scale=0.9,
    eye_shape="circle",        # ring shape
    eye_dot_shape="dot",       # centre dot shape
    eye_ring=1.2,              # ring thickness in modules
    eye_scale=1.0,             # whole-eye scale
    eye_dot_scale=0.9,         # centre dot scale
    eye_fg="#ff0080",          # eyes get their own colour source
)
qr.save("eyes.png", scale=12)
```

When `eye_shape` is omitted, the eyes inherit the module shape; the `minimal` and `ice` presets are good starting points for small-eye looks.

***

## 6. Shaders

Shaders are applied in order after the symbol is rasterised. Pass names (optionally with `:key=value` parameters), `("name", {params})` pairs, callables or `Shader` objects.

```python
import qrforge

qr = qrforge.QR("shaders", ec="h")
qr.use_style(module_shape="rounded", module_radius=0.28,
             fg=["#00f0ff", "#7b2ff7", "#ff2ec4"], bg="#0a0118",
             shaders=["glow:radius=2,amount=0.75", "grain:amount=0.06"])

qr.save("glow.png", scale=12)
qr.save("glow.svg")     # shaders with an SVG equivalent are embedded as filters
```

Write your own per-pixel shader. It receives pixel coordinates, the current `Color` and a `Context` with helpers such as `uv()`, `radius()`, `noise()` and `rand()`:

```python
import qrforge

@qrforge.shader
def heat(x, y, color, ctx):
    u, v = ctx.uv(x, y)                   # 0..1 over the whole canvas
    return color.mix("#ff4400", v)

qr = qrforge.QR("heat", ec="h").use_style(module_shape="square", fg="#ffe0b2",
                                          shaders=[heat, "vignette:amount=0.4"])
qr.save("heat.png", scale=12)
```

For quick experiments use a one-line expression (formulas must return a `Color`):

```python
import qrforge

shader = qrforge.expression("mix(c, Color((255 * u, 128 * v, 200 * r)), 0.6)")
qr = qrforge.QR("expression", ec="h").use_style(shaders=[shader])
qr.save("expression.png", scale=12)
```

{% hint style="warning" %}
Not every shader has an SVG equivalent. Warp and post effects such as `twist`, `bulge`, `glitch` and `halftone` are raster-only and are skipped silently in SVG output.
{% endhint %}

***

## 7. Logos

A logo image can be a path, bytes, a `Pixmap` or a Pillow image. qrforge carves a knockout zone so the surrounding modules stay readable.

```python
import qrforge

qr = qrforge.QR("https://example.com", ec="h")   # use the highest EC level with logos
qr.use_style(
    module_shape="dot",
    fg=["#ff0080", "#7928ca"],
    logo="logo.png",
    logo_size=0.26,               # width as a fraction of the symbol width
    logo_shape="rounded",         # square | rounded | circle
    logo_radius=0.4,              # corner radius of the cut-out, in modules
    logo_padding=0.75,            # clear zone around the logo, in modules
    logo_bg="#ffffff",            # colour behind the logo (None keeps what is underneath)
    logo_stroke=("#000000", 0.2), # (colour, width in modules)
    logo_rotation=0,
    logo_opacity=1.0,
)
qr.save("logo.png", scale=14)
print(qr.verify())                # confirm the symbol still scans
```

{% hint style="info" %}
Logos cover data modules, so increase the error correction level (`ec="h"`) and keep `logo_size` modest (roughly 0.22–0.30). Always call `qr.verify()` or scan the result before shipping it.
{% endhint %}

***

## 8. Textures

A texture is painted *inside* the dark modules instead of a flat `fg`. It accepts the same sources as a logo.

```python
import qrforge
from qrforge import Pixmap

# build a small texture in code (works without Pillow)
texture = Pixmap(64, 64)
for y in range(64):
    for x in range(64):
        texture.set(x, y, (x * 4 % 256, y * 4 % 256, 160, 255))
texture.save("texture.png")

qr = qrforge.QR("texture demo", ec="h")
qr.use_style(
    module_shape="square",
    texture="texture.png",
    texture_mode="cover",        # cover | contain | stretch
    texture_blend="multiply",    # source | multiply | screen | overlay | tint
    texture_opacity=0.9,
)
qr.save("texture_qr.png", scale=12)
```

***

## 9. Backgrounds, cards and shadows

```python
import qrforge

qr = qrforge.QR("styled background", ec="h")
qr.use_style(
    module_shape="rounded", module_radius=0.3,
    fg="#111827",
    bg="#fff6ec",                     # background colour or gradient
    padding=2,                        # extra padding around the symbol, in modules
    quiet_zone=4,                     # the spec asks for 4; keep it unless you control the surrounding artwork
    bg_radius=0.06,                   # rounded "card" corners (fraction of symbol width)
    shadow={"color": "#0b1020", "dx": 2, "dy": 6, "blur": 5, "opacity": 0.25},
)
qr.save("card.png", scale=12)

# use an image behind the symbol
qr.use_style(bg_image="photo.png", bg_opacity=0.35)

# fully transparent PNG (no background, no card)
qrforge.QR("transparent", ec="h").use_style(bg=None, module_shape="dot",
                                            fg=["#00c6ff", "#0072ff"]) \
    .save("transparent.png", scale=12)
```

`stroke=(colour, width_in_modules)` outlines every module, and `supersample=2` (raster only) uses extra sampling passes for smoother edges on very large renders.

***

## 10. Every output format

```python
import qrforge

qr = qrforge.QR("https://github.com/infinitode/qrforge", ec="h").use_style("neon")

# files – the format follows the extension
qr.save("out.png", scale=12)      # PNG (pure-Python codec)
qr.save("out.svg")                # vector SVG
qr.save("out.pdf")                # single-page vector PDF
qr.save("out.html")               # standalone HTML page with the SVG inlined
qr.save("out.txt")                # plain-text blocks
qr.save("out.ansi")               # terminal text with ANSI colour codes
qr.save("out.webp", scale=12)     # WebP, BMP, GIF, TIFF … (requires Pillow)

# JPEG needs an RGB buffer, because the rendered artwork is RGBA
qr.to_pil(scale=12).convert("RGB").save("out.jpg")

# bytes / strings
png_bytes = qr.png(scale=12)      # PNG bytes
svg_text = qr.svg()               # SVG document as a string
pdf_bytes = qr.pdf()

# terminal & text
print(qr.terminal())              # ANSI half-blocks with true colour
print(qr.terminal(color=False))   # same layout without escape codes
print(qr.ascii("##", "  "))       # plain text art

# Pillow (requires Pillow)
image = qr.to_pil(scale=12)

# the render() shortcut returns an Artwork you can inspect or re-save
art = qr.render(scale=12)
art.kind                          # 'pixmap'
art.width, art.pixmap.height      # pixel dimensions
art.to_bytes()                    # PNG bytes
art.to_data_uri()                 # data:image/png;base64,… (for HTML/CSS)
art.save("artwork.png")
```

In Jupyter, a `qrforge.QR` renders inline: `render()` returns an `Artwork` whose `_repr_png_` / `_repr_svg_` hooks display the image, and `Artwork._repr_html_` produces an `<img>` tag.

***

## 11. Presets

```python
import qrforge

qrforge.presets.names()
# ['badge', 'blueprint', 'brutal', 'circuit', 'classic', 'confetti', 'cross',
#  'dots', 'film', 'glitch', 'gold', 'halftone', 'ice', 'leaf', 'minimal',
#  'neon', 'retro', 'rounded', 'soft', 'starry', 'sunset', 'vapor']

# apply a preset by name …
qr = qrforge.QR("preset").use_style("sunset")

# … or build a Style and override any field
style = qrforge.presets.get("sunset", bg="#000000", scale=14)
qr = qrforge.QR("preset").use_style(style)

# register your own preset so it can be used by name everywhere
qrforge.presets.register("midnight", module_shape="star", fg="#8ef6ff",
                         bg="#05070f", shaders=("glow:radius=2,amount=0.7",))
qrforge.save("preset", "midnight.png", "midnight", scale=12)
```

{% hint style="info" %}
When you call `use_style("preset")`, the preset's defaults are applied *underneath* the style you already customised, so your explicit tweaks survive. `qr.styled("preset")` returns a new code instead of mutating the original.
{% endhint %}

***

## 12. Reusing a style across many codes

```python
import qrforge

style = qrforge.Style(module_shape="dot", module_scale=0.92,
                      fg=["#00c6ff", "#0072ff"], bg="#0a0f1c")

for label, url in [("docs", "https://docs.example.com"),
                   ("app", "https://app.example.com")]:
    qr = qrforge.QR(url, ec="h")
    qr.use_style(style)              # mutate in place
    qr.save(f"{label}.png", scale=12)

# styled() returns a copy with a different style
base = qrforge.QR("https://example.com", ec="h")
print(base.styled("gold"))
print(base.styled(module_shape="cross", eye_shape="cross"))

# inspect every option a Style accepts
print(qrforge.style.options())
```

***

## 13. Verifying symbols

```python
import qrforge
from qrforge.verify import decode

qr = qrforge.QR("https://example.com", ec="h")
print(qr.verify())     # 'https://example.com'

# decode a raw module matrix (0 = light, 1 = dark)
result = decode([list(row) for row in qr.matrix.modules])
print(result.text, result.version, result.level, result.mask, result.corrected)

# error correction in action: damage a couple of data modules and read it back
damaged = [list(row) for row in qr.matrix.modules]
for row, col in [(20, 20), (19, 19)]:
    damaged[row][col] ^= 1
print(decode(damaged))
# DecodeResult(text='https://example.com', …, corrected=1)
```

`corrected` is the number of codewords Reed–Solomon had to repair, which makes it a handy metric when tuning aggressive styles.

***

## 14. Batch generation

```python
import os
import qrforge

os.makedirs("qrcodes", exist_ok=True)

urls = {
    "home": "https://example.com",
    "docs": "https://docs.example.com",
    "status": "https://status.example.com",
}

style = qrforge.Style(module_shape="rounded", module_radius=0.3,
                      fg=["#00f0ff", "#7b2ff7"], bg="#0a0118",
                      shaders=("glow:radius=2,amount=0.7",))

for name, url in urls.items():
    qr = qrforge.QR(url, ec="h").use_style(style)
    qr.save(f"qrcodes/{name}.png", scale=12)
    qr.save(f"qrcodes/{name}.svg")
    assert qr.verify() == url
```

The same job from the command line:

```bash
mkdir -p qrcodes
for name in home docs status; do
  qrforge "https://${name}.example.com" -o "qrcodes/${name}.png" -p neon -s 12 -e H
done
```

***

## 15. Working with the encoder directly

The low-level modules are importable when you need them (for example to embed QR matrices in a custom renderer):

```python
import qrforge
from qrforge import encoder, matrix

qr_matrix = matrix.build("HELLO", level="M")      # versions are chosen automatically
print(qr_matrix.version, qr_matrix.size, qr_matrix.dark_ratio())

segments = encoder.segment("HELLO 123", qr_matrix.version, mode="auto")
codewords = encoder.encode_codewords("HELLO 123", qr_matrix.version, "M")

print(segments, len(codewords))
print(qr_matrix.to_dict()["version"])
```

See [Presets & Outputs](/documentation/package-documentation/qrforge-package-documentation/qrforge-reference/qrforge-presets-and-outputs.md) for the module map and the remaining helpers.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://infinitode-docs.gitbook.io/documentation/package-documentation/qrforge-package-documentation/qrforge-usage-examples.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
