Skip to main content

sextants

Convert raster images (JPEG, PNG, …) to teletext / viewdata block-mosaic graphics — the 40×25 character page rendered by the SAA5050 and its relatives (BBC Micro Mode 7, Ceefax/Oracle teletext, Prestel viewdata, CEPT videotex).

The name comes from Unicode's own term for the 2×3 sub-pixel mosaic cell these displays draw — the sextants of the "Symbols for Legacy Computing" block (U+1FB00…). Each cell is six sub-pixels sharing a two-colour sub-palette, and a colour change is an in-band control code that costs a whole cell. Encoding an image well is therefore a constrained optimisation, not a simple resample — which is what this library does, row by row, with an optimal dynamic-programming solver.

Attribution

sextants is a derivative work of image2mode7 / image2teletext by Kieran Connell. The conversion algorithm at its heart — the per-row dynamic-programming solver, the sub-pixel error model, and the preprocessing pipeline — is Kieran's work, used here under its MIT licence. This project repackages that code as an installable, src-layout Python library with a split module structure, a Click CLI, and a test suite, and is the basis for further development. Please see LICENSE for the full notice.

Install

uv add sextants           # or: pip install sextants

Optional numba acceleration for the DP solver:

uv add "sextants[fast]"

Library usage

from pathlib import Path
from PIL import Image
from sextants import convert, convert_image, render_preview
from sextants import PreprocessOptions, SolveOptions

# Preset-aware entry point: a named bundle configures the whole pipeline.
page = convert(Image.open("photo.jpg"), preset="photo")   # 1000-byte teletext page
Path("photo.bin").write_bytes(page)                        # load at &7C00 on a BBC Micro
render_preview(page).save("preview.png")                   # what it looks like on-screen

# Or drive every knob directly with the two typed option groups.
page = convert_image(
    "logo.png",
    preprocess=PreprocessOptions(quant_colors=8, snap=40, saturation=2.0),
    solve=SolveOptions(edge_weight=3.0),
)

convert(image, preset=None, *, preprocess=None, solve=None) is the preset-aware entry point; convert_image(image, preprocess=None, solve=None) takes the options directly. Configuration lives in two frozen, validated dataclasses — PreprocessOptions (tone, colour, palette, resize) and SolveOptions (the per-row solver and its error metric). Passing preprocess= or solve= to convert replaces that whole stage's options; the preset's other stage still applies. Presets bundle sensible options for common sources:

Preset For
photo Portraits, landscapes, general photos
clean Safe universal default; light denoise + snap for unknown/BBS images
smooth Noisy JPEGs, soft gradients
vivid / graphic / flat Punchy colour, logos/cartoons, bold posterised
retro / art Authentic Ceefax look, hand-crafted teletext-art look
level1 Source is already a Mode 7 / Level 1 teletext image
dark / tv / crt Exposure lift; LCD (PAR 1.2); CRT (PAR 1.22)

Command line

sextants photo.jpg -o photo.bin --preset photo
sextants photo.jpg --preview preview.png --url    # also print an edit.tf URL
sextants --help

The output is a raw 1000-byte page (25 rows × 40 bytes of teletext character codes). It loads directly at &7C00 on a BBC Micro, or paste the --url into edit.tf.

Development

uv sync            # create the environment
uv run pytest      # run the test suite

Licence

MIT — see LICENSE. Original algorithm © 2020 Kieran Connell; packaging and modifications © 2026 Robert Smallshire.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sextants-0.4.0.tar.gz (32.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sextants-0.4.0-py3-none-any.whl (38.7 kB view details)

Uploaded Python 3

File details

Details for the file sextants-0.4.0.tar.gz.

File metadata

  • Download URL: sextants-0.4.0.tar.gz
  • Upload date:
  • Size: 32.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sextants-0.4.0.tar.gz
Algorithm Hash digest
SHA256 f935bb9874e01cb17c9c98c1c505349e95bb09668042b25de08543533c408167
MD5 8309c7089cd51b2414d0a72d397d14c3
BLAKE2b-256 9e3431a454367c183c072f40c70239e0d9e6d7caaf10f5ef5b6d02cbdf39792b

See more details on using hashes here.

File details

Details for the file sextants-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: sextants-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 38.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sextants-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8ed083d52b477b296457d1cc9b49b7c627b9906e4e952db70dfe3de1a513d70
MD5 37f2a35aa1a1056767beb68490f9305e
BLAKE2b-256 8f76f1f22c1de4cc3763390e68347dd9215e38fb0370a34af9588125a85659ab

See more details on using hashes here.

Release history Release notifications | RSS feed

0.5.0

2 files

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.0

2 files

0.1.1

2 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