ICC::Support::CMF - An object oriented module for calculating custom color matching functions (CMFs).
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]);
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.
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.
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)
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
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.
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)
The object hash is updated directly. There is no error checking! If the set value is invalid, the object may fail.
Updating the 'field' value won't change the optical densities.
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)
These calculations are for an individual observer.
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.
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)
These calculations are for a standard observer. This is explained in section 4 of Stockman and Rider's paper (see "Papers and Presentations").
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.
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)
These calculations are for an individual observer.
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.
The calculated CMFs involve several intermediate steps. Outputs with value 'undef' and not calculated or needed.
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
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
Colour & Vision Research Laboratory http://www.cvrl.org/main.php
Munsell Color Science Laboratory https://www.rit.edu/science/munsell-color-lab/
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
pyCone Software https://github.com/CVRL-IoO/Individual-CMFs.git
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.
William B. Birkett, <wbirkett@doplganger.com>
Copyright © 2004-2026 by William B. Birkett