#grayscale #alpha #map #rgba #color #graphics

chromatic

A small utility library for building and sampling colour maps

5 releases

Uses new Rust 2024

0.0.5 May 4, 2025
0.0.4 May 4, 2025
0.0.3 May 3, 2025
0.0.2 May 1, 2025
0.0.0 Apr 29, 2025

#52 in Visualization

Download history 121/week @ 2025-04-25 328/week @ 2025-05-02 29/week @ 2025-05-09

478 downloads per month
Used in photo

MIT license

120KB
2.5K SLoC

Chromatic

Crates.io Documentation License: MIT

A comprehensive Rust library with a straightforward API for working with multiple colour spaces.

Features

  • Extensive colour space support: RGB, sRGB, HSL, HSV, Lab, XYZ, and greyscale
  • Alpha channel variants: All colour spaces have alpha channel counterparts (e.g., RGBA, HSLA)
  • Generic type representation: Use any floating-point type as the underlying representation (f32, f64, etc.)
  • Flexible colourmap creation: Build and sample from colour gradients with any colour space
  • Rich conversion system: Convert between any supported colour spaces
  • CLI friendly: Display impls print ANSI-coloured blocks so you can eyeball gradients right in your terminal.
  • Format flexibility: Convert to/from hex strings and byte arrays
  • Complete colour mixing: Linear interpolation, perceptual colour differences, proper gamma handling for sRGB

Installation

Add chromatic to your Cargo.toml:

[dependencies]
chromatic = "0.1.0"

Quick Start

use chromatic::{Colour, ColourMap, Rgb, Hsv, Lab, Xyz, Convert};
use num_traits::Float;

// Create colours in different spaces
let red = Rgb::new(1.0, 0.0, 0.0);
let green = Rgb::new(0.0, 1.0, 0.0);
let blue = Rgb::new(0.0, 0.0, 1.0);

// Convert between colour spaces
let red_hsv = red.to_hsv();
let red_lab = red.to_lab();

// Create a colour map
let colours = [red, green, blue];
let positions = [0.0, 0.5, 1.0];
let cmap = ColourMap::<Rgb<f32>, f32, 3>::new(&colours, &positions);

// Sample colours from the map
let orange = cmap.sample(0.25); // Between red and green
let teal = cmap.sample(0.75);   // Between green and blue

// Display colours in terminal
println!("Red: {}", red);
println!("Orange: {}", orange);
println!("Green: {}", green);
println!("Teal: {}", teal);
println!("Blue: {}", blue);
println!("Colour map: {}", cmap);

Colour Spaces

Chromatic provides the following colour spaces:

Space Description Components
Grey Greyscale Monochromaic intensity
Rgb Linear RGB Red, Green, Blue
Srgb sRGB (gamma-corrected) Red, Green, Blue
Hsl HSL Hue, Saturation, Lightness
Hsv HSV Hue, Saturation, Value
Lab CIE Lab* Lightness, a*, b*
Xyz CIE XYZ X, Y, Z

Each colour space also has an alpha variant (e.g., GreyAlpha, RgbAlpha, etc.).

Working with Colour Maps

Colour maps allow you to create gradients between multiple colours:

use chromatic::{Colour, ColourMap, Hsv};

// Create a rainbow colour map in HSV space
let rainbow = [
    Hsv::new(0.0, 1.0, 1.0),    // Red
    Hsv::new(60.0, 1.0, 1.0),   // Yellow
    Hsv::new(120.0, 1.0, 1.0),  // Green
    Hsv::new(180.0, 1.0, 1.0),  // Cyan
    Hsv::new(240.0, 1.0, 1.0),  // Blue
    Hsv::new(300.0, 1.0, 1.0),  // Magenta
    Hsv::new(360.0, 1.0, 1.0),  // Red again
];

// Create a uniformly spaced colour map
let cmap = ColourMap::<Hsv<f32>, f32, 3>::new_uniform(&rainbow);

// Print the colour map to see the gradient
println!("{}", cmap);

// Sample a colour from the map
let sampled_colour = cmap.sample(0.5);

Colour Conversions

All colours can be converted between spaces using the Convert trait:

use chromatic::{Colour, Convert, Rgb, Hsv, Lab};

let red = Rgb::new(1.0, 0.0, 0.0);

// Convert to other spaces
let red_hsv = red.to_hsv();
let red_lab = red.to_lab();

// Convert to string representation
let hex = red.to_hex();
println!("Red in hex: {}", hex); // #FF0000

// Parse colour from hex
let parsed_red = Rgb::<f32>::from_hex("#FF0000").unwrap();

Perceptual Colour Differences

Chromatic includes methods to calculate perceptual colour differences:

use chromatic::{Lab, Convert, Rgb};

let colour1 = Rgb::new(0.8, 0.3, 0.4);
let colour2 = Rgb::new(0.7, 0.4, 0.45);

// Convert to Lab for perceptual difference calculation
let lab1 = colour1.to_lab();
let lab2 = colour2.to_lab();

// Calculate perceptual colour difference using Delta E
let basic_delta_e = lab1.delta_e(&lab2);
let improved_delta_e = lab1.delta_e94(&lab2);

println!("Basic Delta E: {}", basic_delta_e);
println!("Improved Delta E (CIE94): {}", improved_delta_e);

Terminal Visualization

All colour types implement Display and can be directly printed in terminals that support 24-bit colour:

use chromatic::{ColourMap, Rgb};

// Create a simple gradient from black to white
let black = Rgb::new(0.0, 0.0, 0.0);
let white = Rgb::new(1.0, 1.0, 1.0);
let gradient = [black, white];

let cmap = ColourMap::<Rgb<f64>, f64, 3>::new_uniform(&gradient);

// Print the entire colour map to visualize the gradient
println!("{}", cmap);

Generic Type Support

Chromatic supports any floating-point type that implements the Float trait from num_traits:

use chromatic::{Rgb, Hsv, Convert};
use num_traits::Float;

// Use f32 for memory efficiency
let red_f32 = Rgb::<f32>::new(1.0, 0.0, 0.0);

// Use f64 for higher precision
let red_f64 = Rgb::<f64>::new(1.0, 0.0, 0.0);

// Function that works with any float type
fn blend_colours<T: Float + Send + Sync>(colour1: &Rgb<T>, colour2: &Rgb<T>, factor: T) -> Rgb<T> {
    Rgb::lerp(colour1, colour2, factor)
}

License

This project is licensed under the MIT License - see the LICENSE file for details.

Dependencies

~2–10MB
~125K SLoC