Crate munsellspace

Crate munsellspace 

Source
Expand description

§MunsellSpace 🎨

High-precision sRGB to Munsell color space conversion with 99.98% reference accuracy.

This library provides the most accurate open-source implementation for converting RGB colors to Munsell notation, validated against the complete 4,007-color reference dataset.

§Quick Start

use munsellspace::MunsellConverter;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let converter = MunsellConverter::new()?;
     
    // Convert RGB to Munsell
    let munsell = converter.srgb_to_munsell([255, 0, 0])?;
    println!("Pure red: {}", munsell); // Output: 7.9R 5.2/20.5
     
    Ok(())
}

§Features

  • 99.98% Accuracy: Validated against complete reference dataset (4,006/4,007 exact matches)
  • High Performance: 4,000+ colors/second batch processing
  • Scientific Precision: Reference data lookup with intelligent interpolation
  • Thread Safety: Full support for concurrent usage with Send + Sync implementations
  • Semantic Color Names: 30 color name overlays from Centore (2020) research
  • Comprehensive Testing: Full test suite with accuracy validation

§About Munsell Color Space

The Munsell color system describes colors using three perceptually uniform dimensions:

  • Hue: Color family (R, YR, Y, GY, G, BG, B, PB, P, RP)
  • Value: Lightness from 0 (black) to 10 (white)
  • Chroma: Saturation from 0 (neutral) to 15+ (vivid)

Example: 5R 4.0/14.0 = medium red (5R) with medium lightness (4.0) and high saturation (14.0).

§Thread Safety

All public types in MunsellSpace are thread-safe and implement Send + Sync. You can safely share converters across multiple threads using Arc<T>:

use munsellspace::{MunsellConverter, IsccNbsClassifier};
use std::sync::Arc;
use std::thread;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create shared instances
    let converter = Arc::new(MunsellConverter::new()?);
    let classifier = Arc::new(IsccNbsClassifier::new()?);
     
    let mut handles = vec![];
     
    // Spawn multiple threads for concurrent processing
    for thread_id in 0..4 {
        let converter_clone = Arc::clone(&converter);
        let classifier_clone = Arc::clone(&classifier);
         
        let handle = thread::spawn(move || {
            // Each thread can safely use the converters concurrently
            let munsell = converter_clone.srgb_to_munsell([255, 0, 0]).unwrap();
             
            if let (Some(hue), Some(chroma)) = (&munsell.hue, munsell.chroma) {
                if let Ok(Some(iscc_color)) = classifier_clone.classify_munsell(hue, munsell.value, chroma) {
                    println!("Thread {}: {} -> {:?}", thread_id, munsell, iscc_color);
                }
            }
        });
         
        handles.push(handle);
    }
     
    // Wait for all threads to complete
    for handle in handles {
        handle.join().unwrap();
    }
     
    Ok(())
}

Internal caches use Arc<RwLock<T>> for safe concurrent access, allowing multiple readers or exclusive writers without data races.

§Semantic Color Names (v1.2.0+)

MunsellSpace includes 30 semantic color name overlays derived from Paul Centore’s 2020 research paper “Beige, aqua, fuchsia, etc.: Definitions for some non-basic surface colour names” (JAIC, 25, 24-54). These overlays define convex polyhedra in Munsell space for each color name, allowing you to determine which color names apply to any given Munsell color.

use munsellspace::{MunsellSpec, semantic_overlay, matching_overlays, get_registry};

fn main() {
    // Parse a Munsell color and find matching color names
    let color = MunsellSpec::new(7.4, 6.2, 3.4); // Near aqua centroid

    // Get the best-matching color name
    if let Some(name) = semantic_overlay(&color) {
        println!("Best match: {}", name);  // "aqua"
    }

    // Get all matching color names (colors can match multiple names)
    let matches = matching_overlays(&color);
    println!("All matches: {:?}", matches);

    // Access the complete registry for advanced use
    let registry = get_registry();
    println!("Registry has {} overlays", registry.len()); // 30
}

Available color names (30 total):

  • Non-basic (20): aqua, beige, coral, fuchsia, gold, lavender, lilac, magenta, mauve, navy, peach, rose, rust, sand, tan, taupe, teal, turquoise, violet, wine
  • Basic (10): blue, brown, gray, green, orange, pink, purple, red, white, yellow

§Unified Color Naming API (v1.2.0+)

The ColorClassifier provides a unified interface for all color naming systems. From any color input, get complete naming information with consistent modifiers across ISCC-NBS standard, extended, and semantic names.

use munsellspace::{ColorClassifier, ColorModifier};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let classifier = ColorClassifier::new()?;

    // Classify any color format
    let desc = classifier.classify_srgb([180, 80, 60])?;

    // Get descriptors from all naming systems
    println!("Standard: {}", desc.standard_descriptor());   // "moderate reddish brown"
    println!("Extended: {}", desc.extended_descriptor());   // "moderate rust"
    if let Some(semantic) = desc.semantic_descriptor() {
        println!("Semantic: {}", semantic);                 // "moderate rust"
    }

    // The same modifier applies across all systems
    println!("Modifier: {:?}", desc.modifier);              // Moderate

    // Format any modifier + color combination
    let formatted = ColorModifier::Vivid.format("coral");
    println!("{}", formatted);                              // "vivid coral"

    Ok(())
}

§Flexible Color Characterization (v1.2.1+)

The new characterization API separates objective color facts from formatting preferences, giving you complete control over how colors are described.

use munsellspace::{ColorClassifier, ColorCharacterization, FormatOptions, BaseColorSet, OverlayMode};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let classifier = ColorClassifier::new()?;

    // Get objective characterization
    let char = classifier.characterize_srgb([0, 0, 128])?;

    // Access raw data
    println!("ISCC-NBS #{}: {}", char.iscc_nbs_number, char.iscc_base_color);
    println!("Semantic matches: {:?}", char.semantic_matches);

    // Format with different preferences
    let standard = FormatOptions::new(BaseColorSet::Standard, OverlayMode::Ignore);
    let with_overlay = FormatOptions::new(BaseColorSet::Extended, OverlayMode::Include);

    println!("Standard: {}", char.describe(&standard));       // "dark blue"
    println!("With overlay: {}", char.describe(&with_overlay)); // "dark navy"

    // Preset options for common cases
    println!("{}", char.describe(&FormatOptions::standard()));           // "dark blue"
    println!("{}", char.describe(&FormatOptions::extended()));           // "dark blue"
    println!("{}", char.describe(&FormatOptions::standard_with_overlays())); // "dark navy"
    println!("{}", char.describe(&FormatOptions::extended_with_overlays())); // "dark navy"

    Ok(())
}

BaseColorSet: Controls which ISCC-NBS names to use

  • Standard: 29 official ISCC-NBS base names (“vivid yellow green”, “dark greenish blue”)
  • Extended: Uses lime/teal/turquoise for compound names (“vivid lime”, “dark teal”)

OverlayMode: Controls semantic overlay behavior

  • Ignore: Always use ISCC-NBS base colors
  • Include: Use nearest semantic overlay when available

Re-exports§

pub use converter::MunsellConverter;
pub use types::MunsellColor;
pub use types::RgbColor;
pub use types::IsccNbsName;
pub use types::IsccNbsPolygon;
pub use types::MunsellPoint;
pub use error::MunsellError;
pub use error::Result;
pub use illuminants::Illuminant;
pub use illuminants::ChromaticAdaptation;
pub use illuminants::ChromaticAdaptationMethod;
pub use iscc::IsccNbsClassifier;
pub use iscc::ColorMetadata;
pub use mechanical_wedges::MechanicalWedgeSystem;
pub use mathematical::MathematicalMunsellConverter;
pub use mathematical::MunsellSpecification;
pub use mathematical::CieXyY;
pub use mathematical::Illuminant as MathematicalIlluminant;
pub use mathematical::ChromaticAdaptation as MathematicalChromaticAdaptation;
pub use reverse_conversion::ReverseConverter;
pub use reverse_conversion::ColorFormats;
pub use reverse_conversion::CieLab;
pub use reverse_conversion::HslColor;
pub use reverse_conversion::HsvColor;
pub use reverse_conversion::munsell_to_hex_string;
pub use unified_cache::UnifiedColorCache;
pub use unified_cache::CachedColorResult;
pub use semantic_overlay::MunsellSpec;
pub use semantic_overlay::MunsellCartesian;
pub use semantic_overlay::SemanticOverlay;
pub use semantic_overlay::SemanticOverlayRegistry;
pub use semantic_overlay::parse_hue_to_number;
pub use semantic_overlay::hue_number_to_string;
pub use semantic_overlay::parse_munsell_notation;
pub use semantic_overlay::semantic_overlay;Deprecated
pub use semantic_overlay::matching_overlays;Deprecated
pub use semantic_overlay::matching_overlays_ranked;Deprecated
pub use semantic_overlay::matches_overlay;Deprecated
pub use semantic_overlay::closest_overlay;Deprecated
pub use semantic_overlay_data::create_overlay_registry;
pub use semantic_overlay_data::get_registry;
pub use color_names::ColorClassifier;
pub use color_names::ColorDescriptor;
pub use color_names::ColorModifier;
pub use color_names::known_color_names;
pub use color_names::is_known_color;
pub use color_names::color_name_count;
pub use color_names::ColorCharacterization;
pub use color_names::FormatOptions;
pub use color_names::BaseColorSet;
pub use color_names::OverlayMode;

Modules§

color_interpolation
Interpolation and extrapolation classes - exact 1:1 port from Python colour-science Line-by-line port with exact behavior matching
color_math_utils
Utility and validation functions - exact 1:1 port from Python colour-science Line-by-line port with exact behavior matching
color_names
Unified color naming API for MunsellSpace
color_notation_parser
String parsing and formatting functions - exact 1:1 port from Python colour-science Line-by-line port with exact behavior matching
constants
Mathematical constants and datasets for Munsell color space conversion
conversion_helpers
Helper functions needed for the Python port These are utility functions used by the main algorithm
converter
High-precision sRGB to Munsell color space converter.
error
Error types for MunsellSpace conversion operations.
illuminants
Standard illuminants and chromatic adaptation
iscc
ISCC-NBS Color Name System Implementation
lab_color_space
Lab color space functions - exact 1:1 port from Python colour-science Line-by-line port with exact behavior matching
mathematical
Mathematical Munsell color space conversion implementation
mechanical_wedges
Mechanical Wedge System for Deterministic ISCC-NBS Color Classification
munsell_color_science
Exact 1:1 port of Python colour-science munsell functions This module contains exact implementations matching Python’s behaviour
munsell_converter_core
Python-compatible Munsell converter This module integrates the exact 1:1 Python ports for accurate conversion
reverse_conversion
Reverse conversion pipeline: Munsell → Lab → sRGB/hex/HSL/HSV
semantic_overlay
Semantic overlay functionality for non-basic color names.
semantic_overlay_data
Semantic overlay registry using Centore polyhedron data.
types
Core types for Munsell color space representation.
unified_cache

Constants§

VERSION
Library version