Skip to main content

Module colorspace

Module colorspace 

Source
Expand description

Theme-relative colorspace for perceptually uniform palette generation.

§Motivation

Terminal 256-color palettes have 240 extended colors (indices 16–255) that are hardcoded with fixed RGB values, completely ignoring the user’s base16 theme. This module implements jake-stewart’s proposal to generate those colors by trilinear interpolation in CIE LAB space using the 8 base ANSI colors as cube corners.

§Concept: Theme-Relative Color

Instead of addressing colors as absolute RGB values, this module lets you specify a position in a color cube whose corners are the user’s theme colors:

Cube cornerANSI color
(0, 0, 0)background (defaults to black)
(1, 0, 0)red
(0, 1, 0)green
(1, 1, 0)yellow
(0, 0, 1)blue
(1, 0, 1)magenta
(0, 1, 1)cyan
(1, 1, 1)foreground (defaults to white)

A CubeCoord like (0.6, 0.2, 0.0) means “60% toward red, 20% toward green, 0% blue” — the theme determines what that actually looks like on screen.

§Why CIE LAB?

LAB is a perceptually uniform colorspace: equal numerical distances correspond to equal perceived color differences. Interpolating in LAB (rather than RGB) ensures:

  • Consistent brightness: blue shades at level 3 look as bright as green at level 3
  • Smooth gradients: no muddy midpoints or perceptual jumps
  • Hue preservation: interpolation follows natural color transitions

§Trilinear Interpolation

The 8 theme colors sit at the corners of a unit cube. For any point (r, g, b) inside the cube, the color is computed by three nested linear interpolations in LAB:

  1. R-axis: Interpolate 4 edge pairs (bg→red, green→yellow, blue→magenta, cyan→fg)
  2. G-axis: Interpolate between the R-axis results to sweep across 2 faces
  3. B-axis: Interpolate between the G-axis results to fill the volume

At every grid point, the resulting color is a smooth blend of all 8 corner colors, weighted by proximity.

§Example

use standout_render::colorspace::{CubeCoord, Rgb, ThemePalette};

// Define a gruvbox-like palette (8 base colors)
let palette = ThemePalette::new([
    Rgb(40, 40, 40),     // black
    Rgb(204, 36, 29),    // red
    Rgb(152, 151, 26),   // green
    Rgb(215, 153, 33),   // yellow
    Rgb(69, 133, 136),   // blue
    Rgb(177, 98, 134),   // magenta
    Rgb(104, 157, 106),  // cyan
    Rgb(168, 153, 132),  // white
]);

// Resolve a theme-relative coordinate to an actual RGB color
let coord = CubeCoord::from_percentages(60.0, 20.0, 0.0).unwrap();
let color = palette.resolve(&coord);

// Generate a full 240-color extended palette (216 cube + 24 grayscale)
let extended = palette.generate_palette(6);
assert_eq!(extended.len(), 240);

Structs§

CubeCoord
A position in the theme-relative color cube.
Rgb
A simple RGB color triplet.
ThemePalette
A set of 8 anchor colors that define a theme-relative color space.