#cie-lab #colorimetry #cie #interface #color #color-model #observer #ciecam16

colorimetry

Rust library for color modeling with JavaScript/WASM interfaces

4 releases

new 0.0.3 Apr 16, 2025
0.0.2 Aug 9, 2024
0.0.1 Aug 9, 2024
0.0.0 Aug 2, 2024

#2 in #observer

Download history 102/week @ 2025-04-11

102 downloads per month

MIT/Apache

1.5MB
12K SLoC

Overview

A Colorimetry Library for color modelling in illumination and engineering projects. Besides being a Rust library, it also provides JavaScript/WebAssembly interfaces, although still rudimentary at this stage. The algorithms are implemented according to recommendations of the International Commission on Illumination (CIE), the International Color Consortium (ICC), and the Illumination Engineering Society (IES).

It is a spectral library, using spectral representations of color, allowing to use more advanced colorimetric observers besides the outdated and flawed CIE 1931 standard observer. It uses spectral representations of illuminants, filters, and color patches defined over a wavelength domain from 380 to 780 nanometers, with 1 nanometer steps. Many spectral representations of illuminants and colorants are included in the library, either by default, or by using feature flags. You can also include use your own data, and if your dataset is defined on a different domain linear, Sprague, and Spline interpolation methods are available to remap.

Installation

To use this library in a Rust application, run the command:

   cargo add colorimetry

or add this line to the dependencies in your Cargo.toml file:

    colorimetry = "0.0.3"

The easiest way to use the objects and functions library is through its prelude. This example calculates the chromaticity values of the CIE D65 illuminant.

    use colorimetry::prelude::*;
    let xy = CIE1931.xyz(&D65, None).chromaticity();
    approx::assert_abs_diff_eq!(xy.as_ref(), [0.3127, 0.3291].as_ref(), epsilon=5E-5);

Features

The library includes many data collections, of which only a minimal set is included by default. A feature is enabled by including using the flag -F. For example, to include "cri" Color Rendering Index module illuminants, use:

    cargo add colorimetry -F cri

or

    cargo add colorimetry --features cri

This can also be set manually, in your cargo.toml file, using

    colorimetry = {version = "0.0.3", features = ["cri"]}

The current features in this library are:

  • cie-illuminants default Include a large collection of standard illuminants such as the Fluorescent and LED series. Included by default. To exclude use the --no-default-features flag: cargo add --no-default-features.
  • supplemental-observers default The CIE 1931 Standard Observer is always included, but with feature several other standard and experimental colorimetric observers are included as well. Included by default.
  • munsell Include reflection spectra for the Munsell colors. This will increase the size of your executable quite a bit, and is not included by default.
  • charts Include reflection spectra for various test charts.
  • cri Include the color rendering index module, which calculates the Ra and R1 to R14 values for illuminants. This loads an additional 14 test color sample spectra.
  • cct Calculate correlated color temperature for illuminants. Builds a 4096 length lookup table, with each row consisting of 3*f64 values. The table rows are only calculated when required, but table space is reserved in the executable. This module is also included with the "cri" feature.
  • color-fidelity Calculates CIE 224:2017 Color Fidelity Index, and associated values. Contains 99 test color samples.

Spectral Distributions

All spectral calculations in this library use the Spectrum class as a base, which contains the spectral data.

For practical considerations, it uses a wavelength domain from 380 to 780 nanometers, with 1 nanometer intervals, as recommended in the CIE15:2004 standard. Spectrum uses a nalgebra::Vector<f64> type, with a length of 401 elements. Historically, different wavelength domains have been recommended and used by the CIE, such as ranges from 300 to 830 nanometers, and an interval size of 5 nanometers. The choice of domain has a small impact on calculated colorimetric values, and the reference values calculated here can differ a bit from the ones published by the CIE in the past.

Lights and Filters

The library distinguishes spectral compositions of light, which have a power, and generated by a source or a display, and represented by a Light trait, and reflection or transmission spectra, which values are limited to a range from 0.0 to 1.0, and which represented by a Filter trait. When lights are combined, their spectral compositions are added. This is called additive mixing, and a combination of lights will have a higher energy than a single light. When filters are combined by placing them between a light and an observer, they take away power from a light, which is called subtractive mixing; subtractive is a bit of a misleading term here, as their spectra are multiplied, not subtracted from a mathematical point of view. A light beam passing through a filter, or reflected by a color patch, will always lose energy.

A Stimulus is a light ray entering our eyes, and being seen

Illuminants

We need light to see. Objects 'get color' only when they are illuminated. In this library a Illuminant is a spectral representation of the light which hits an object.

The most common illuminant is daylight. The CIE has defined the D65 standard illuminant, and recommends using this as default daylight illuminant. Here we use the StdIlluminant to represent the CIE recommended standard illuminants, in particular StdIlluminant::D65 for default daylight.

Another source of light are electric lamps, such as incandescent light bulbs. They generate light by thermal emission from a very hot tungsten filament in a glass envelope. In physics, the spectral properties of thermal emission is described by Planck's law. For incandescent light bulbs, the CIE recommends using the A-illuminant, in this library available as StdIlluminant::A.

For example, to get the A illuminant's chromaticity:

    use colorimetry::prelude::*;

    let xy_a = CIE1931.xyz(&StdIlluminant::A, None).chromaticity();
    // see <https://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_A>
    approx::assert_abs_diff_eq!(xy_a.as_ref(), [0.44758, 0.40745].as_ref(), epsilon=1E-5)

Non-standard illuminants are represented by a Illuminant. These can be initiated with your own data, or you can use one of the many constructors provided. One example of this is the Illuminant::planckian constructor, which generates a spectrum in accordance with Planck's law, taking an absolute temperature with a unit of Kelvin as argument. The example calculates the Illuminance and CIE 1931 (x, y) chromaticity coordinates for a Planckian (thermal emission-based) illuminator with a Correlated Color Temperature of 3000 Kelvin using the CIE 1931 standard observer.

    use crate::colorimetry::prelude::*;

    let p3000 = Illuminant::planckian(3000.0);
    let xy = CIE1931.xyz(&p3000, None).chromaticity();

    approx::assert_abs_diff_eq!(xy.as_ref(), [0.436_935,0.404_083].as_ref(), epsilon = 1E-6);

Illuminant and StdIlluminant both implement the Light trait, which is used as generic input for color models.

Stimuli

Other interesting constructors are the Stimulus::srgb, and Stimulus::rgb, which create a spectrum of a set of RGB pixel values. The first takes three u8 arguments, while the second uses a RGB object as argument.

    use colorimetry::prelude::*;
    let red = Stimulus::srgb(255, 0, 0);
    approx::assert_abs_diff_eq!(
        CIE1931.xyz(&red, None).chromaticity().as_ref(),
        &[0.64, 0.33].as_ref(),
        epsilon = 1E-5
    );

The CIE Standard Colorimetric Observer

What we perceive as color are sensations in the virtual cortex located in the back of our brain. These sensations are triggered by stimuli from the photosensitive layer in the back of our eyes, called retina. Human vision is trichromatic, which means that light, when entering our eyes, is classified by three stimuli. In colorimetry, at the physiological level, these stimuli are represented by the X, Y, and Z tristimulus values, using the CIE XYZ color model, and using three types of color sensitivity functions, called color matching functions, for an average or standard observer. Color matching functions are indirect representations of the spectral sensitivities of the L, M, and S cones in our retinas, as function of spectral stimuli entering our eyes.

The first and currently still almost exclusively used standard observer is the CIE 1931 Colorimetric Standard Observer. The definition of this observer by the CIE launched the field of colorimetry. In this library it is represented by a static instance of the Observer class called CIE1931 and is always available. With the default supplemental-observers feature also other observers are included, such as the CIE 1976 10º, s, the CIE 2015 2º and CIE 2015 10º observers.

The primary function of a Observer, such as the CIE1931 colorimetric standard observer, is the CIE1931.xyz method, which takes a spectral distribution as a single argument, and produces a XYZ object, encapsulating the CIE 1931 X, Y, and Z tristimulus values. These tristimulus values are used by more advanced color models, such as the CIELAB and CIECAM, to describe the sensations of color in our minds.

Paints, Dyes, and Inks

These are represented by a Colorant object, which encapsulates a reflection or transmission spectrum, defined over a domain from 380 to 780 nanometers with 1 nanometer steps, and values within a range from 0.0 to 1.0. They implement the Filter trait, which is used as input for many of the color models.

XYZ Tristimulus Values

These tristimulus values are a representation of the response of each of the three cones, and an inproduct of the spectrum and the color matching functions. All color models are using the tristimulus values of a stimulus, essentially a light ray being detected by a set of cones, as a basis.

Although they can be initiated in this library directly using the XYZ::new constructor, they are typical produced by using the Observer::xyz function, which takes a generic Light and an optional Filter argument. Examples of object which implement the Light trait are StdIlluminant and Illuminant.

CieLab Color Model

Likewise, the lab_d65 and lab_d50 methods can be used to get CIELAB coordinates for a spectrum measured from a color sample, as an instance of the CieLab class.

Color

RGB Color Values, and RgbSpace Color Spaces.

Correlated Color Temperature

Color Rendering Metrics

Use with Deno/TypeScript

Use in Web Applications

License

All content ©2024 Harbers Bik LLC, and licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~6–16MB
~196K SLoC