Open Source • AGPL-3.0 • Built on Reticulum

RHI Codec

A new image and video codec designed for mesh networks. Encodes photos as braille characters with per-element color. Transmits as native text over any channel. Progressive delivery. Video over LoRa. Open source.
2.5 KB
Photo at 30w avg
0.3 KB
Video delta frame
Color resolution vs prior art
0
Dependencies

The Problem

Reticulum can move bytes over anything — LoRa, WiFi, serial, sound. But there's no image format designed for these transports. JPEG is binary-only and bloated at low bandwidth. You can't send a photo natively over LXMF text. And when a NomadNet page goes offline, the images go with it.

RHI fixes this. Images encoded as text, small enough for LoRa, with quality that actually looks good.

Live Demo — The Full Transformation

Source photograph → RHI braille encoding → client-side reconstruction. Same image at four resolutions. The braille is real Unicode text — select it, copy it. The reconstructed images are what the receiver sees after bilinear upscale.

Source Image (400×596)
Mona Lisa — Leonardo da Vinci, c. 1503 (public domain)
20w — Micro Tier 40×56 native pixels
~1.9 KB












⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Worst-case LoRa (≤1 KB/s). Recognizable in under 2 seconds. This is what “images over LoRa” looks like.
30w — LoRa Tier 60×80 native pixels
~2.3 KB



⠀⠀
⠀⠀









⠀⠀

⠀⠀⠀
⠀⠀⠀⠀⠀

⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Standard LoRa (2-4 KB/s). The sweet spot. Transmits as text or compact binary. Clearly recognizable.
50w — WiFi Tier 100×148 native pixels
~6 KB





⠀⠀⠀
⠀⠀⠀
⠀⠀⠀⠀
⠀⠀⠀⠀
⠀⠀


⠀⠀






⠀⠀⠀

⠀⠀

⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
WiFi or good Bluetooth. Getting detailed. Facial features clear. Still only 6 KB.
80w — Broadband Tier 160×236 native pixels
~15 KB
⣿⣿

⣿⣿⣿⣿
⣿⣿
⣿⣿


⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⣿⣿⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
TCP or broadband link. Near-photographic. The braille grid is so dense it looks like a texture. 15 KB total.

Every resolution above is independently decodable.

The 1.9 KB micro tier and the 15 KB broadband tier use the same codec, same format, same renderer. Progressive delivery sends the small one first, refines with larger tiers as bandwidth allows. Unlike progressive JPEG, every tier looks like a real image.

How It Works

📷
Source
Any image
⠀⣿
Encode
Braille grid
🎨
Color
Per-dot RGB
📡
Transmit
2.3 KB
🖼
Reconstruct
Full color

Each braille character carries 6 independent RGB colors — one per dot. The receiver reconstructs a full-color image from the grid data. No codec dependencies. Just JavaScript.

What's New Here

Prior Art (single color per character)

Existing braille/block art uses one color per character. ASCII art, terminal graphics, all of it. One character = one color. Low resolution. Looks like a terminal.

RHI (independent color per element)

Each braille character has 6 dots. Each dot carries its own RGB color. Same character, 6× the color data. Looks like a photograph. Transmits as text.

Features

Text Wire Format
Encoded images are Unicode text. Send over LXMF, SMS, IRC, email, amateur radio — any text channel. No base64. No binary decoder needed.
Binary Wire Format
Palette compression for bandwidth-critical links. ~2.5 KB average for a photo at 30 chars wide. Smaller than BMP or PNG at the same resolution. Transmits as text where JPEG cannot.
Video Delta Compression
Cell-level differencing. Only changed cells transmit. 0.3 KB per delta frame. Sustained video at 0.6 KB/s over LoRa.
Progressive Delivery
First 2.5 KB = recognizable image. Refinement layers add detail. Unlike progressive JPEG, every layer looks like a real photo.
Adaptive Quality Tiers
Auto-adjusts resolution based on link quality. LoRa gets 25w. WiFi gets 80w+. Congestion fallback built in.
Client-Side Reconstruction
Bilinear upscale + configurable color correction. 26 user-facing controls. Zero codec dependencies. Runs in any browser.
Multi-Mode Rendering
Same data → pixel, dot, overlap, or smooth rendering. Client-side choice. Zero bandwidth difference.
QR Codes Survive
QR codes encoded through RHI at 25w remain scannable after reconstruction. Tested with phone camera. Identity exchange over LoRa.

Measured Sizes

WidthNative PixelsRHI BinaryJPEG q=10BMPPNG
25w50×33~2.0 KB~0.7 KB3.4 KB4.2 KB
30w60×40~2.5 KB~0.7 KB4.7 KB5.1 KB
50w100×66~5.8 KB~0.9 KB13.3 KB10.8 KB
80w160×106~13.9 KB~1.3 KB34.1 KB24.0 KB

JPEG produces smaller files at every resolution — it's a mature codec optimized for photographic compression. RHI's advantage is not raw size. It's that RHI transmits as native Unicode text over any text channel (LXMF, SMS, IRC, amateur radio), supports progressive delivery where every layer is recognizable, provides cell-level delta compression for video, requires zero codec dependencies to reconstruct, and gives the receiver 26 creative controls over the output. RHI is smaller than BMP and PNG at the same resolution.

Video Over LoRa

MetricValue
Full frame (30w binary)~2.5 KB
Delta frame (typical motion)~0.3 KB
Compression ratio8–20× per frame
Sustained bandwidth~0.6 KB/s at 2 FPS
Display framerate (interpolated)15 FPS

Quick Start

# Python — encode an image from rhi_codec import RHIEncoder enc = RHIEncoder( width=30, # braille grid width dots=6, # 6-dot (2×3) preferred all_dots=True, # keep every pixel use_palette=True, # indexed color compression ) data = enc.encode_image("photo.jpg") # data is ~2-4 KB. Send it over LXMF, LoRa, anything.
// JavaScript — reconstruct in browser // rhive-renderer.js — zero dependencies, canvas 2D const renderer = new RHIRenderer(canvas, { sharpen: 1.5, // aggressive at low res autoLevels: true, }); renderer.renderFrame(decodedGrid);

Why 6-Dot Braille?

A/B/C tested 5 character systems: 8-dot braille (2×4), 6-dot braille (2×3), quadrant blocks (2×2), sextant characters (2×3), raw pixels (1×1). 6-dot won on visual quality — the 2:3 aspect ratio produces more natural image proportions than 2:4. Wider font support (U+2800–U+283F). 64 patterns per character.

What This Is For

Built for Reticulum. This codec was designed from the ground up for mesh networks. It works at 500 bytes per second. It transmits as text over LXMF. It reconstructs in any browser with zero dependencies. If you're building on Reticulum, this is for you.

The Art Tool — 26 Controls

The reconstruction pipeline isn't just decode + upscale. It's a full creative tool. The receiver controls how the image looks. Same data, infinite styles.

Detail
Sharpen, Smooth, Auto-levels — edge recovery scales inversely with resolution. Max sharpen at 25w, minimal at 80w+.
Light & Color
Brightness, Contrast, Gamma, Shadows, Highlights, Saturation, Warmth, Hue — full color grading from the same data.
Effects
Vignette, Grain, Posterize, Invert, Emboss, Chromatic Split, Dither, Channel Swap, Mirror.
Vector
Edges, Quantize, Threshold, Flatten, Duotone — from photographic to woodcut to pop art to thermal vision.
Warm Portrait
Sharpen max, brightness +28, gamma 0.85, shadows +12
Woodcut
Flatten 0.6, edges 0.35, sharpen max, grain
Thermal Vision
Invert, hue +85, sat 1.45, edges, quantize, chroma split

There are no "correct" settings. Different images want different treatment. The controls ARE the feature. The sender tweaks before encoding. The receiver applies their own adjustments. Same data, different aesthetic.

Try it yourself

The full 26-control art tool is included in the source. Upload any image, adjust every parameter, see the reconstruction live. File: tuner.html

Source Code

AGPL-3.0 — free for open source use.

Use it, modify it, build on it. If you deploy a modified version as a service, share your changes. That's the deal.

Commercial license available for closed-source products. Contact: infinitegrok@gmail.com

Patent pending: US Application 64/014,800

Encoder (Python): rhi_codec.py

Renderer (JavaScript): rhive-renderer.js

Art tool / tuner: tuner.html (all 26 controls, upload any image)

Who Built This

Independent developer building a social platform on Reticulum. The codec came out of trying to solve image and video transport over LoRa. It works.

Contact: infinitegrok@gmail.com