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 + Syncimplementations - 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 colorsInclude: Use nearest semantic overlay when available
§Edge Cases and Limitations
§Near-black colors (Value < 0.2)
The Munsell Renotation Dataset contains no entries below Value 0.2. Colors that compute to a Munsell Value below this threshold (roughly sRGB [0,0,0] through [12,12,12]) are returned as neutral (N) with chroma 0, because there is no renotation data to resolve their hue or chroma, and human color discrimination is negligible at such low luminance levels.
let converter = MunsellConverter::new()?;
let near_black = converter.srgb_to_munsell([1, 1, 1])?;
assert_eq!(near_black.notation, "N 0.0"); // Treated as neutral black§Pure black
RGB [0,0,0] returns N 0.0 (neutral black with Value 0 and chroma 0).
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::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
- 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.
- 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