NAME

ICC::Support::CMF - An object oriented module for calculating custom color matching functions (CMFs).

SYNOPSIS

    use ICC::Support::CMF;

    # create a new object
    $cmf = ICC::Support::CMF->new(); # default attributes
    $cmf = ICC::Support::CMF->new($attr); # from an attribute hash

    # get CMFinfo hash
    $info = $cmf->CMFinfo();

    # calculate all spectral sensitivities
    $obj = $cmf->calculateSpectralsensitivities();

    # calculate all 'normal' spectral sensitivities
    $obj = $cmf->calculateSpectralsensitivities_Normal();

    # calculate XYZ CMFs for use by Color.pm object
    ($range, $xyz) = $cmf->calculateCMF(); # default range
    ($range, $xyz) = $cmf->calculateCMF($range); # specify desired wavelength range

    # dump object
    $string = $cmf->sdump([$format]);
    $cmf->dump([$format]);

DESCRIPTION

Colorimetry is based on color matching functions (CMFs) derived from human observers. In 1931 the CIE published CMF tables for the 2º field of view, and in 1964, for the 10º field of view. In 2006, the CIE published "cone-fundamental-based tristimulus functions" for 2º and 10º. These functions are based on measurements of cone sensitivities and the transmittance of the lens and macular region of the eye. The Color.pm module supports all of these CIE standard observers (2, 10, 2P, 10P).

In 2016, Stockman and Rider developed a software program to generate custom CMFs, similar to the cone-fundamental-based ones published by the CIE. The software has parameters to adjust the CMFs for normal variations among individuals. This Perl module is derived from that orignal python software (see "Software"). These custom CMFs may be invoked from the colorimetry hash used by the Color.pm and Chart.pm modules.

Object structure

An ICC::Support::CMF object is a blessed hash reference. The hash contains the custom parameters (CMFinfo), and tables of intermediate CMF calculations (outputs).

    my $self = {
        CMFinfo => {
            step_size => 1.0,

            # cone shifts / optical densities
            Lshift => 0.0,
            Mshift => 0.0,
            Sod    => 0.40,
            Mod    => 0.50,
            Lod    => 0.50,

            # ocular media scaling targets
            mac  => 0.35,    # macular pigment density at 460 nm
            lens => 1.7649,  # lens pigment density at 400 nm

            # RGB primary wavelengths for derived CMFs
            Rnm => 645.15,
            Gnm => 526.32,
            Bnm => 444.44,

            # field of view, currently 2º or 10º
            field => 2,
        },

        # Flags for “two-template” cases (from python UI codons logic)
        LisM      => 0,     # if true: use MMSconelog (two M templates)
        MisL      => 0,     # if true: use LLSconelog (two L templates)
        LisMshift => 0.0,   # extra shift for the “L is M” hybrid template
        MisLshift => 0.0,   # extra shift for the “M is L” hybrid template

        # Outputs (populated by calculation methods)
        nm                     => undef,
        nm_step                => undef,
        LMS_array_size         => undef,
        mac                    => undef,
        lens                   => undef,
        coneabs_template        => undef,
        log_coneabs_template    => undef,
        conenewq_retina         => undef,
        log_conenewq_retina     => undef,
        conenewq_cornea         => undef,
        log_conenewq_cornea     => undef,
        conenewe_cornea         => undef,
        log_conenewe_cornea     => undef,
        RGBCMFs                 => undef,

        # Normal outputs (equivalent to CIE cone-fundamental-based calculations)
        coneabs_template_N      => undef,
        log_coneabs_template_N  => undef,
        conenewq_retina_N       => undef,
        log_conenewq_retina_N   => undef,
        conenewq_cornea_N       => undef,
        log_conenewq_cornea_N   => undef,
        conenewe_cornea_N       => undef,
        log_conenewe_cornea_N   => undef,
        RGBCMFs_N               => undef,
    };

This module is derived from a python program (see "Software") which has a GUI. It only computes CMF functions from the given parameters. These computations are done in several steps, which produce intermediate outputs that are stored within the object.

Calculations are done by calling methods that start with "calculate". These methods access parameters in the 'CMFinfo' hash and save the results of each calculation step as one of the output hash values. Each output is an nx4 array containing the wavelength and L, M, S values. In general, we have no use for these outputs, but they are there if needed.

Note there is a method to calculate "Normal" CMFs and corresponding "Normal" outputs. These calculations are equivalent to those used to produce the "cone-fundamental-based" CMFs published by the CIE. The L values are computed as a weighted average of two common genetic variations. This is explained in section 4 of the paper by Stockman and Rider (see "Papers and Presentations"). This makes sense for a standard observer, but not for an individual observer.

The calculateCMF() method outputs an XYZ CMF, which is the product of a 3x3 matrix and the LMS CMF array. This 3x3 matrix depends on the field of view, which is also a parameter. This method is meant to interface directly with the Color.pm module. It outputs a range array describing the wavelengths, and an XYZ array containing the CMFs.

METHODS

Creating ICC::Support::CMF objects

new

This method creates an ICC::Support::CMF object, setting CMF model parameters with an optional argument hash.

Usage

    $cmf = ICC::Support::CMF->new();
    $cmf = ICC::Support::CMF->new($hash); # with argument hash

Examples

    use ICC::Support::CMF;

    $cmf = ICC::Support::CMF->new(); # default parameter values
    $cmf = ICC::Support::CMF->new({'Mshift' => 2.5}); # M cone shift of 2.5nm (see note 1)
    $cmf = ICC::Support::CMF->new({'field' => 10}); # 10º field of view (see note 2)
  1. The argument hash may have the following keys:

        'Lshift' - wavelength shift of L cones in nm, -40 to +10
        'Mshift' - wavelength shift of M cones in nm, +30 to -20
    
        'Sod' - optical density of S cones
        'Mod' - optical density of M cones
        'Lod' - optical desnity of L cones
    
        'mac' - macular pigment density at 460 nm
        'lens' - lens pigment density at 400 nm
    
        'field' - field of view, 2 or 10 degrees
    
        'Rnm' - red primary wavelength for RGB CMFs in nm
        'Gnm' - green primary wavelength for RGB CMFs in nm
        'Bnm' - blue primary wavelength for RGB CMFs in nm
  2. The field of view is 2º by default. If set to 10º, optical densities of the cones and macular pigment are updated to the correct nominal values.

General accessors

CMFinfo

This method returns a reference to the CMFinfo hash (see "Object structure" section).

Usage

    $info = $cmf->CMFinfo(); # get CMFinfo hash ref

Examples

    use ICC::Support::CMF;
    use Data::Dumper;

    $cmf = ICC::Support::CMF->new(); # create default CMF object
    $info = $cmf->CMFinfo(); # get CMFinfo hash ref

    print Dumper($info); # dump the hash

    $Mshift = $info->{'Mshift'}; # get the 'Mshift' value
    $info->{'Mshift'} = 3.6; # set the 'Mshift' value (see note 1)

    $info->{'field'} = 10; # set the 'field' value (see note 2)
  1. The object hash is updated directly. There is no error checking! If the set value is invalid, the object may fail.

  2. Updating the 'field' value won't change the optical densities.

Calculations

calculateSpectralsensitivities

This method calculates an LMS CMF for an individual observer using the current CMFinfo parameters. This involves several intermediate calculations, which are available as outputs.

Usage

    $obj = $cmf->calculateSpectralsensitivities();

Examples

    use ICC::Support::CMF;
    use Data::Dumper;

    $cmf = ICC::Support::CMF->new(); # create default CMF object
    $cmf->calculateSpectralsensitivities(); # calculate CMF outputs (see note 1)

    print Dumper($cmf->{'conenewe_cornea'}); # print the corneal energy CMF

    $Data::Dumper::Maxdepth= 1;
    print Dumper($cmf); # print the top level object structure (see note 2)
  1. These calculations are for an individual observer.

  2. The calculated CMFs involve several intermediate steps. Each step is output as linear and log values. The keys that are 'undef' are for the 'normal' CMFs, which are not calculated by this method.

calculateSpectralsensitivities_Normal

This method calculates an LMS CMF for a standard observer, equivalent to the CIE cone-fundamental-based CMFs. This involves several intermediate calculations, which are available as outputs.

Usage

    $obj = $cmf->calculateSpectralsensitivities_Normal();

Examples

    use ICC::Support::CMF;
    use Data::Dumper;

    $cmf = ICC::Support::CMF->new(); # create default CMF object
    $cmf->calculateSpectralsensitivities_Normal(); # calculate "normal" CMF outputs (see note 1)

    print Dumper($cmf->{'conenewe_cornea_N'}); # print the "normal" corneal energy CMF

    $Data::Dumper::Maxdepth= 1;
    print Dumper($cmf); # print the top level object structure (see note 2)
  1. These calculations are for a standard observer. This is explained in section 4 of Stockman and Rider's paper (see "Papers and Presentations").

  2. The calculated CMFs involve several intermediate steps. Each step is output as linear and log values. The keys that are 'undef' are for the 'individual' CMFs, which are not calculated by this method.

calculateCMF

This method calculates an XYZ CMF for an individual observer. This involves several intermediate calculations, which are available as outputs.

Usage

    ($range, $xyz) = $cmf->calculateCMF([$range]);

Examples

    use ICC::Support::CMF;
    use Data::Dumper;

    $cmf = ICC::Support::CMF->new(); # create default CMF object
    ($range, $xyz) = $cmf->calculateCMF(); # calculate XYZ CMF outputs (see note 1)

    print Dumper($range, $xyz); # print range and XYZ CMF (see note 2)

    $Data::Dumper::Maxdepth= 1;
    print Dumper($cmf); # print the top level object structure (see note 3)
  1. These calculations are for an individual observer.

  2. The range and XYZ CMF arrays are inputs to the Color.pm module. The XYZ CMF is a 3x3 matrix multiplied by the LMS CMF.

  3. The calculated CMFs involve several intermediate steps. Outputs with value 'undef' and not calculated or needed.

General

dump, sdump

This method returns a string showing the structure of the Color object.

Usage

    $string = $cmf->sdump([$format]);
    $cmf->dump([$format]);

Examples

    use ICC::Support::CMF;

    $cmf = ICC::Support::CMF->new();
    $string = $cmf->sdump(); # dump to string
    $cmf->dump(); # dump to STDOUT

SEE ALSO

CIE Standards

CIE 15 Colorimetry

CIE 170 Fundamental chromaticity diagram with physiological axes

CIE 203 A Computerized Approach to Transmission and Absorption Characteristics of the Human Eye

Color Research Organizations

Colour & Vision Research Laboratory http://www.cvrl.org/main.php

Munsell Color Science Laboratory https://www.rit.edu/science/munsell-color-lab/

Papers and Presentations

Formulae for generating standard and individual human cone spectral sensitivities (Stockman and Rider) https://onlinelibrary.wiley.com/doi/full/10.1002/col.22879

ICC Presentation on Individual Color Matching Functions https://www.color.org/events/vienna/1.AndrewStockman_ICC_LEDMax_ICMFs.pdf

Software

pyCone Software https://github.com/CVRL-IoO/Individual-CMFs.git

LICENSE

Programs in this distribution, authored by William B. Birkett, are licensed under the GNU General Public License, v3.

See https://www.gnu.org/licenses/gpl-3.0.html for license details.

AUTHOR

William B. Birkett, <wbirkett@doplganger.com>

COPYRIGHT

Copyright © 2004-2026 by William B. Birkett

<<