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.
| Family | Spaces |
|---|---|
| sRGB and linear | Color::Rgb, Color::LinearRgb |
| Cylindrical sRGB | Color::Hsl, Color::Hsv, Color::Hwb |
| CIE | Color::Lab, Color::Lch, Color::Luv, Color::Lchuv, Color::Xyz50, Color::Xyz65 |
| Oklab | Color::Oklab, Color::Oklch, Color::Okhsl, Color::Okhsv |
| Wide-gamut RGB | Color::P3, Color::Rec2020, Color::A98, Color::ProphotoRgb |
| DIN99o | Color::Dlab, Color::Dlch |
| JzAzBz / ICtCp | Color::Jab, Color::Jch, Color::Itp |
| HSLuv | Color::Hsluv, Color::Hpluv |
| Other | Color::Cubehelix, Color::Hsi, Color::Yiq, Color::Xyb, Color::Prismatic |
Color::Prismatic is a culors extension; culori 4.0.2 has no
Prismatic mode.
§Public API tour
Coloris the tagged union over every supported space. Each variant wraps the matching struct fromspaces.- The
ColorSpacetrait definesto_xyz65/from_xyz65for every space, plus alpha access. convert()is the generic conversion function. It routes through XYZ D65, so any pair ofColorSpaceimplementors works without enumerating conversion paths. For bit-exact culori parity on precision-critical pairs, use the directFromimpls listed inconvert, or the dynamic-dispatchColor::convert_to/ typedconvert::convert_culoriAPIs 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, andcolor-mix()). Malformed or unsupported input yieldsNone.format_cssserializes aColorto canonical CSS.interpolate()/interpolate_with()return a closureFn(f64) -> Colorthat samples a multi-stop ramp att ∈ [0, 1]in the requested space.HueFixupselects the cylindrical fixup strategy.blend()/blend_str()fold a stack of colors with one of the 12 separableBlendModemodes, using Porter-Duff source-over with premultiplied alpha. Output is alwaysColor::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_gamutprovide the gamut-mapping ladder, withto_gamutimplementing 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 closuresFn(&Color, &Color) -> f64. wcag_luminanceandwcag_contrastimplement the WCAG 2.x contrast formula on sRGB.- The
filter_*family (brightness,contrast,grayscale,hue_rotate,invert,saturate,sepia, plus CVDprot/deuter/trit) returns a closureFn(&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): derivesSerializeandDeserializefor every space struct and forColor.
§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.jsfamily. 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
ColorSpacetrait — every color space implements it.