Skip to main content

Crate culors

Crate culors 

Source
Expand description

A Rust port of culori, the JavaScript color library by Dan Burzo.

culors implements 30+ color spaces, conversion between any pair of them, a CSS Color Module 4 string parser and matching formatter, interpolation, gamut mapping, ΔE, separable blend modes, mode-aware averaging, WCAG contrast, and the CSS filter set. Output values agree with culori 4.0.2 within 1e-10 across an exhaustive fixture set (110 conversion pairs, 365 parse cases, 303 format round-trips).

§Quick start

Parse two CSS strings, blend them, and format the result back:

use culors::{blend, format_css, parse, BlendMode};

let red = parse("#ff0000").unwrap();
let blue = parse("rgb(0 0 255 / 0.5)").unwrap();
let mixed = blend(&[red, blue], BlendMode::Multiply);
let css = format_css(&mixed);
assert!(css.starts_with("color(srgb"));

Parse, convert, and format:

use culors::{convert, format_css, parse, Color};
use culors::spaces::Lab;

let parsed = parse("oklch(70% 0.15 30deg)").expect("valid CSS");
let lab: Lab = match parsed {
    Color::Oklch(c) => convert(c),
    _ => unreachable!("oklch(...) parses as Color::Oklch"),
};
let css = format_css(&Color::Lab(lab));
assert!(css.starts_with("lab("));

§Supported color spaces

Spaces are exposed as plain structs in spaces and as variants of Color.

Color::Prismatic is a culors extension; culori 4.0.2 has no Prismatic mode.

§Public API tour

  • Color is the tagged union over every supported space. Each variant wraps the matching struct from spaces.
  • The ColorSpace trait defines to_xyz65 / from_xyz65 for every space, plus alpha access.
  • convert() is the generic conversion function. It routes through XYZ D65, so any pair of ColorSpace implementors works without enumerating conversion paths. For bit-exact culori parity on precision-critical pairs, use the direct From impls listed in convert, or the dynamic-dispatch Color::convert_to / typed convert::convert_culori APIs added in v1.2 — both follow culori’s per-pair routing.
  • parse() consumes CSS Color Module 4 syntax (named colors, hex, functional notation, color() profiles including the four wide-gamut spaces, and color-mix()). Malformed or unsupported input yields None.
  • format_css serializes a Color to canonical CSS.
  • interpolate() / interpolate_with() return a closure Fn(f64) -> Color that samples a multi-stop ramp at t ∈ [0, 1] in the requested space. HueFixup selects the cylindrical fixup strategy.
  • blend() / blend_str() fold a stack of colors with one of the 12 separable BlendMode modes, using Porter-Duff source-over with premultiplied alpha. Output is always Color::Rgb.
  • average(), average_number(), average_angle() reduce a slice of colors / numbers / hue angles in a chosen mode.
  • in_gamut, clamp_gamut, clamp_chroma, to_gamut provide the gamut-mapping ladder, with to_gamut implementing the CSS Color Module 4 algorithm using ΔE OK.
  • The difference_* family (Ciede76, Ciede94, Ciede2000, CMC, OK, JzAzBz, ICtCp, Euclidean, hue-chroma, hue-saturation) returns curried closures Fn(&Color, &Color) -> f64.
  • wcag_luminance and wcag_contrast implement the WCAG 2.x contrast formula on sRGB.
  • The filter_* family (brightness, contrast, grayscale, hue_rotate, invert, saturate, sepia, plus CVD prot / deuter / trit) returns a closure Fn(&Color) -> Color.

§Interpolation

use culors::{interpolate, parse};

let a = parse("oklch(70% 0.15 30deg)").unwrap();
let b = parse("oklch(70% 0.15 200deg)").unwrap();
let ramp = interpolate(&[a, b], "oklab");
let mid = ramp(0.5);
let _ = mid;

§WCAG contrast

use culors::{parse, wcag_contrast};

let bg = parse("white").unwrap();
let fg = parse("black").unwrap();
let ratio = wcag_contrast(&bg, &fg);
assert!(ratio > 20.0);

§ΔE

use culors::{difference_ciede2000, parse};

let de = difference_ciede2000(1.0, 1.0, 1.0);
let red = parse("red").unwrap();
let crimson = parse("crimson").unwrap();
assert!(de(&red, &crimson) > 0.0);

§Feature flags

  • serde (off by default): derives Serialize and Deserialize for every space struct and for Color.

§Status

As of v1.5 culors tracks culori 4.0.2 at full feature parity, modulo the intentional divergences listed in the README. The library is in maintenance mode: new features land in culori first; once accepted upstream they’re mirrored here. Bug fixes and culori version bumps remain in scope.

§Further reading

See the project README for the features matrix, comparison to culori, and v1.0 known divergences. Release history is in CHANGELOG.md.

§License

MIT-licensed.

Re-exports§

pub use average::average;
pub use average::average_angle;
pub use average::average_number;
pub use blend::blend;
pub use blend::blend_str;
pub use blend::BlendMode;
pub use color::Color;
pub use color::ColorVariantMismatch;
pub use contrast::wcag_contrast;
pub use contrast::wcag_luminance;
pub use convert::convert;
pub use convert::convert_culori;
pub use convert::converter;
pub use difference::difference_ciede2000;
pub use difference::difference_ciede76;
pub use difference::difference_ciede94;
pub use difference::difference_ciede94_with;
pub use difference::difference_cmc;
pub use difference::difference_euclidean;
pub use difference::difference_euclidean_with;
pub use difference::difference_euclidean_xyz;
pub use difference::difference_hue_chroma;
pub use difference::difference_hue_naive;
pub use difference::difference_hue_saturation;
pub use difference::difference_hyab;
pub use difference::difference_itp;
pub use difference::difference_jz;
pub use difference::difference_kotsarenko_ramos;
pub use difference::difference_ok;
pub use easing::easing_gamma;
pub use easing::easing_in_out_sine;
pub use easing::easing_midpoint;
pub use easing::easing_smootherstep;
pub use easing::easing_smoothstep;
pub use easing::easing_smoothstep_inverse;
pub use filter::filter_brightness;
pub use filter::filter_contrast;
pub use filter::filter_deficiency_deuter;
pub use filter::filter_deficiency_prot;
pub use filter::filter_deficiency_trit;
pub use filter::filter_grayscale;
pub use filter::filter_hue_rotate;
pub use filter::filter_invert;
pub use filter::filter_saturate;
pub use filter::filter_sepia;
pub use format::format_css;
pub use format::format_hex;
pub use format::format_hex8;
pub use format::format_hsl;
pub use format::format_rgb;
pub use gamut::clamp_chroma;
pub use gamut::clamp_gamut;
pub use gamut::clamp_rgb;
pub use gamut::displayable;
pub use gamut::in_gamut;
pub use gamut::to_gamut;
pub use interpolate::fixup_alpha;
pub use interpolate::fixup_hue_decreasing;
pub use interpolate::fixup_hue_increasing;
pub use interpolate::fixup_hue_longer;
pub use interpolate::fixup_hue_shorter;
pub use interpolate::interpolate;
pub use interpolate::interpolate_with;
pub use interpolate::interpolate_with_premultiplied_alpha;
pub use interpolate::interpolator_piecewise;
pub use interpolate::interpolator_spline_basis;
pub use interpolate::interpolator_spline_basis_closed;
pub use interpolate::interpolator_spline_monotone;
pub use interpolate::interpolator_spline_monotone_2;
pub use interpolate::interpolator_spline_monotone_closed;
pub use interpolate::interpolator_spline_natural;
pub use interpolate::interpolator_spline_natural_closed;
pub use interpolate::normalize_positions;
pub use interpolate::ChannelInterp;
pub use interpolate::ChannelInterpFactory;
pub use interpolate::HueFixup;
pub use interpolate::InterpolateOptions;
pub use lerp::blerp;
pub use lerp::lerp;
pub use lerp::trilerp;
pub use lerp::unlerp;
pub use map::map_alpha_divide;
pub use map::map_alpha_multiply;
pub use map::map_transfer_gamma;
pub use map::map_transfer_linear;
pub use map::mapper;
pub use nearest::nearest;
pub use parse::parse;
pub use random::random;
pub use random::random_with_constraints;
pub use round::round;
pub use samples::samples;
pub use samples::samples_with_easing;
pub use traits::ColorSpace;

Modules§

average
Color averaging across CSS Color Module 4 spaces.
blend
CSS Compositing & Blending.
color
Dynamic color enum.
contrast
WCAG 2.1 luminance and contrast helpers. Mirrors culori 4.0.2’s wcag.js (luminance, contrast).
convert
Color-space conversion.
difference
Color-difference (ΔE) factories. Mirrors culori 4.0.2’s difference.js family. Each public function returns a closure that computes the configured metric on a pair of colors.
easing
Scalar easing curves.
filter
CSS-style image filters.
format
CSS Color Module 4 formatter.
gamut
Gamut mapping: deciding when a color sits inside a target gamut and producing the closest in-gamut color when it does not.
interpolate
Color interpolation across CSS Color Module 4 spaces.
lerp
Scalar linear, bilinear, and trilinear interpolation utilities.
map
Per-channel transfer pipeline.
nearest
Palette nearest-color search, mirroring culori 4.0.2’s nearest.js.
parse
CSS Color Module 4 string parser.
random
Random color generation, mirroring culori 4.0.2’s random.js.
round
Rounding factory matching culori’s round.js.
samples
Evenly spaced ramp samples.
spaces
Color-space implementations. One module per space.
traits
The ColorSpace trait — every color space implements it.