β# documentation for Shared.pm module / 2019-10-09
=encoding utf8
=head1 NAME
ICC::Shared - Parent class for ICC::Profile and ICC::Support modules.
=head1 SYNOPSIS
use parent 'ICC::Shared'; # add as parent class (to another module)
use ICC::Shared; # export all functions and constants
use ICC::Shared qw(Lab2xyz xyz2Lab D50); # export selected functions and a constant
# copy an object
$clone = $obj->copy(); # copy an object
@clones = $obj->copy(4); # make an array of 4 copies
# store an object
$flag = $obj->store($file_path); # store serialized object
# print object structure
$obj->dump();
$obj->dump($format);
# Math::Matrix additions
$matrix->sdump([$format]); # print object contents to string
$matrix->dump([$format]); # print object contents
$matrix2 = $matrix->power($exponent); # exponentiate matrix elements, exponent may be a scalar or vector
$matrix2 = $matrix->xyz2XYZ([$XYZ_white_point]); # convert matrix working space from xyz to XYZ
$matrix2 = $matrix->XYZ2xyz([$XYZ_white_point]); # convert matrix working space from XYZ to xyz
# color encoding functions
@Lab = xyz2Lab(@xyz); @xyz = Lab2xyz(@Lab); # array
$Lab = xyz2Lab($xyz); $xyz = Lab2xyz($Lab); # vector, matrix, array structure
@Lxyz = xyz2Lxyz(@xyz); @xyz = Lxyz2xyz(@Lxyz); # array
$Lxyz = xyz2Lxyz($xyz); $xyz = Lxyz2xyz($Lxyz); # vector, matrix, array structure
@Lab = Lxyz2Lab(@Lxyz); @Lxyz = Lab2Lxyz(@Lab); # array
$Lab = Lxyz2Lab($Lxyz); $Lxyz = Lab2Lxyz($Lab); # vector, matrix, array structure
@Lab = XYZ2Lab(@XYZ); @XYZ = Lab2XYZ(@Lab); # array (D50)
$Lab = XYZ2Lab($XYZ); $XYZ = Lab2XYZ($Lab); # vector, matrix, array structure (D50)
@Lab = XYZ2Lab(@XYZ, $wtpt); @XYZ = Lab2XYZ(@Lab, $wtpt); # array
$Lab = XYZ2Lab($XYZ, $wtpt); $XYZ = Lab2XYZ($Lab, $wtpt); # vector, matrix, array structure
@Lxyz = XYZ2Lxyz(@XYZ); @XYZ = Lxyz2XYZ(@Lxyz); # array (D50)
$Lxyz = XYZ2Lxyz($XYZ); $XYZ = Lxyz2XYZ($Lxyz); # vector, matrix, array structure (D50)
@Lxyz = XYZ2Lxyz(@XYZ, $wtpt); @XYZ = Lxyz2XYZ(@Lxyz, $wtpt); # array
$Lxyz = XYZ2Lxyz($XYZ, $wtpt); $XYZ = Lxyz2XYZ($Lxyz, $wtpt); # vector, matrix, array structure
@XYZ = xyz2XYZ(@xyz); @xyz = XYZ2xyz(@XYZ); # array (D50)
$XYZ = xyz2XYZ($xyz); $xyz = XYZ2xyz($XYZ); # vector, matrix, array structure (D50)
@XYZ = xyz2XYZ(@xyz, $wtpt); @xyz = XYZ2xyz(@XYZ, $wtpt); # array
$XYZ = xyz2XYZ($xyz, $wtpt); $xyz = XYZ2xyz($XYZ, $wtpt); # vector, matrix, array structure
@xyY = XYZ2xyY(@XYZ); @XYZ = xyY2XYZ(@xyY); # array
$xyY = XYZ2xyY($XYZ); $XYZ = xyY2XYZ($xyY); # vector, matrix, array structure
$L = x2L($x); $x = L2x($L); # CIE L* function
$dLdx = dLdx($x); $dxdL = dxdL($L); derivative of CIE L* function
$jac = xyz2Lab_jac($xyz); # Jacobian matrix of xyz2Lab function
$jac = Lab2xyz_jac($Lab); # Jacobian matrix of Lab2xyz function
$W = XYZ2W(@XYZ, $wtpt); # CIE Whiteness
$dwv = xyz2dwv($xyz); # density weighted value
# color difference functions
$dE = dEab(@Lab1, @Lab2); # CIE βE*ab color difference
$dE = dE94(@Lab1, @Lab2); # CIE βE94 color difference
$dE = dE00(@Lab1, @Lab2); # CIE βE00 color difference
$dE = dE99(@Lab1, @Lab2); # DIN99 color difference
$dE = dE99(@Lab1, @Lab2, Ke, Kch); # DIN99 color difference
$dE = dEcmc(@Lab1, @Lab2); # CMC(l:c) color difference
$dE = dEcmc(@Lab1, @Lab2, l, c); # CMC(l:c) color difference
($dL, $dCh) = dLCh(@Lab1, @Lab2); # βL*, βCh β G7 grayscale compliance
($dL, $da, $db) = dLab(@Lab1, @Lab2); # simple color difference
# illuminant functions
($cct, $err) = CCT($x, $y); # correlated color temperature
$cct = CCT2($x, $y); # correlated color temperature using McCamy's approximation
$rad = bbrad($nm, $T); # black body radiance using Planck's law
($x, $y) = bbxy($T); # chromaticity of black body radiator
($u, $v) = bbuv($T); CIE UCS 1960 of black body radiator
($u, $v) = XYZ2ucs(@XYZ); # CIE UCS 1960
($u, $v) = xy2ucs(@xy); # CIE UCS 1960
($range, $spd) = daylight($cct); range and SPD of daylight
# interpolation functions
$vec_out = linear($vec_in, $range_in, $range_out); # interpolate a vector (linear)
$matrix = linear_matrix($range_in, $range_out); # make interpolating matrix (linear)
$vec_out = cspline($vec_in, $range_in, $range_out); # interpolate a vector (natural cubic spline)
$matrix = cspline_matrix($range_in, $range_out); # make interpolating matrix (natural cubic spline)
$vec_out = lagrange($vec_in, $range_in, $range_out); # interpolate a vector (Lagrange, ASTM E 2022)
$matrix = lagrange_matrix($range_in, $range_out); # make interpolating matrix (Lagrange, ASTM E 2022)
# vector functions
$scalar = dotProduct($vec1, $vec2); # vector dot product
$vector = crossProduct($vec1, $vec2); # vector cross product
# utility functions
$vector = flatten($structure); # flatten an array structure
clip_struct($structure); # clip each element of an array structure
$integer = round($value); # round off value to nearest integer (+/-)
$vector = s15f162v($s15f16); # convert from s15Fixed16Number vector
$s15f16 = v2s15f16($vector); # convert to s15Fixed16Number vector
(profiles_folder_path, directory_segs, customer, job) = makeProfileFolder(file/folder_path); # make folder for profiles
(profiles_folder_path, directory_segs, customer, job) = makeProfileFolder(file/folder_path, alias_folder_path);
$path = getICCPath(); # get path to 'ICC' distribution folder
$path = getICCPath('Data'); # get path to 'ICC' distribution 'Data' folder
$path = getICCPath('Data/ASTM_E308_data.yml'); # get path to 'ICC' distribution 'ASTM_E308_data.yml' file
filterPath($path); # interpret '~' and '\' in file paths
setFile(path_to_file, creator, type); # set Mac OSX creator and file type (deprecated by Apple)
$array_ref = parse_tokens($token_string); # splits string into tokens, and parses any parameters
# parameter testing functions
$flag = is_vector($vec); # test if parameter is a vector (values may be numeric or undef)
$flag = is_num_vector($vec); # test if parameter is a vector (values must be numeric)
$flag = is_matrix($mat); # test if parameter is a matrix (values may be numeric or undef)
$flag = is_num_matrix($mat); # test if parameter is a matrix (values must be numeric)
# constants
D50 β D50 illuminant XYZ values (CIE 1931 2 degree observer)
d50 β D50 illuminant XYZ values, encoded as 32-bit ICC XYZNumber
d50P β D50 illuminant XYZ values, encoded as 16-bit ICC XYZ
PI β circumference of a unit circle, approximately 3.14159
radian β degrees in a radian, approximately 57.29578
ln10 β natural logarithm of 10, approximately 2.30258
=head1 DESCRIPTION
ICC::Shared is a parent class for all ICC::Profile and ICC::Support modules. It includes a collection of useful functions and constants.
=head2 Data structure and functions
Many functions provided by this module take color data for their input. All of these functions will take an array as input.
Some functions will also take vector, matrix and array structure inputs, as noted in the B<Usage> section. Here are examples
of the various data structures,
@list = (50, 20, 20); # single sample, an array, also known as a list
$vector = [50, 20, 20]; # single sample, a vector
$matrix = [
[50, 20, 20],
[50, 20, 20],
[50, 20, 20],
]; # multiple samples, a matrix, also known as a 2-D array
$struct = [
[50, 20, 20],
[
[50, 20, 20],
[50, 20, 20],
]
]; # multiple samples, an array structure
Functions that take vector, matrix and array structure inputs will return the same data type and structure.
=head2 Color spaces
There are many ways to encode colorimetric measurements. These are normally called color spaces.
The basic calculation of colorimetry from spectral measurements produces so-called tristimulus values β the CIE XYZ
color space. By convention, the XYZ values of an illuminant are scaled so that the Y-value is 100. A perfectly white
reference sample will have the same XYZ values as the illuminant.
When the XYZ values of a sample are divided by the XYZ values of the illuminant, the result is xyz values (lower case),
which normally range from 0 - 1 (unless there is fluorescence).
In 1976, the CIE standardized a perceptually uniform color space called CIE L*a*b*. The transformation from xyz to
L*a*b* is non-linear. The x, y and z values are passed through an identical non-linear transform. The transformed y
value is known as L* or lightness. The a* and b* values are computed from the difference between the transformed y
value, and the the transformed x and z values.
The intermediate L*a*b* calculation, where x, y and z are transformed non-linearly, is often useful. This is called
Lxyz color space. It is not a CIE standard color space.
The color encoding functions below convert all 12 combinations of these color spaces β XYZ, xyz, L*a*b* and Lxyz.
The 6 functions involving XYZ require the illuminant white point. If this is omitted, D50 illuminant is used.
Sometimes XYZ values are converted to chromaticity values, or xyY color space. The x and y values indicate color, and
the Y value Lightness. This color space is generally used for illuminants.
=head1 METHODS
=head2 Common methods
=head3 copy
This method copies (clones) an object. The copies are separate objects.
B<Usage>
$clone = $obj->copy(); # copy an object
@clones = $obj->copy(4); # make an array of 4 copies
B<Examples>
use ICC::Profile;
$curve = ICC::Profile::curv->new([0, 1]); # make a 'curv' object
$curve_set = ICC::Profile::cvst->new([$curve->copy(4)]); # make a 'cvst' object
=head3 store
This method stores an object using the 'Storable::store' function.
B<Usage>
$flag = $obj->store($file_path); # store serialized object
$obj = Storable::retrieve($file_path); # retrieve the object
=head3 dump
This method prints the structure of an object.
B<Usage>
$obj->dump();
$obj->dump($format);
B<Examples>
use ICC::Profile;
$profile = ICC::Profile->new('~/Desktop/my_profile.icc'); # make a 'Profile' object
$profile->dump(); # print the object structure
=head2 Math::Matrix additions
A few methods are appended to the standard Math::Matrix module. Rather than subclass a new module, we just put them
in the Math::Matrix name space.
=head3 sdump
print object contents to string
=head3 dump
print object contents
=head3 clip
clip matrix elements
=head3 power
exponentiate matrix elements
=head3 xyz2XYZ, XYZ2xyz
convert matrix working space between xyz and XYZ
=head1 FUNCTIONS
=head2 Color encoding functions
=head3 xyz2Lab, Lab2xyz
These functions convert between xyz and L*a*b* encoding.
B<Usage>
@Lab = xyz2Lab(@xyz); @xyz = Lab2xyz(@Lab); # array
$Lab = xyz2Lab($xyz); $xyz = Lab2xyz($Lab); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$xyz = $chart->xyz([], {'encoding' => 9}); # get all xyz data
$Lab = xyz2Lab($xyz); # convert xyz matrix to L*a*b* encoding
$xyz_rt = Lab2xyz($Lab); # convert back to xyz encoding
$vector = xyz2Lab($xyz->[0]); # convert a vector
@array = xyz2Lab(@{$xyz->[0]}); # convert an array
=head3 xyz2Lxyz, Lxyz2xyz
These functions convert between xyz and Lxyz encoding.
B<Usage>
@Lxyz = xyz2Lxyz(@xyz); @xyz = Lxyz2xyz(@Lxyz); # array
$Lxyz = xyz2Lxyz($xyz); $xyz = Lxyz2xyz($Lxyz); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$xyz = $chart->xyz([], {'encoding' => 9}); # get all xyz data
$Lxyz = xyz2Lxyz($xyz); # convert xyz matrix to Lxyz encoding
$xyz_rt = Lxyz2xyz($Lxyz); # convert back to xyz encoding
$vector = xyz2Lxyz($xyz->[0]); # convert a vector
@array = xyz2Lxyz(@{$xyz->[0]}); # convert an array
=head3 Lab2Lxyz, Lxyz2Lab
These functions convert between L*a*b* and Lxyz encoding.
B<Usage>
@Lxyz = Lab2Lxyz(@Lab); @Lab = Lxyz2Lab(@Lxyz); # array
$Lxyz = Lab2Lxyz($Lab); $Lab = Lxyz2Lab($Lxyz); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$Lab = $chart->Lab([]); # get all L*a*b* data
$Lxyz = Lab2Lxyz($Lab); # convert L*a*b* matrix to Lxyz encoding
$Lab_rt = Lxyz2Lab($Lxyz); # convert back to L*a*b* encoding
$vector = Lab2Lxyz($Lab->[0]); # convert a vector
@array = Lab2Lxyz(@{$Lab->[0]}); # convert an array
=head3 XYZ2Lab, Lab2XYZ
These functions convert between XYZ and L*a*b* encoding.
B<Usage>
@Lab = XYZ2Lab(@XYZ); @XYZ = Lab2XYZ(@Lab); # array (D50)
$Lab = XYZ2Lab($XYZ); $XYZ = Lab2XYZ($Lab); # vector, matrix, array structure (D50)
@Lab = XYZ2Lab(@XYZ, $wtpt); @XYZ = Lab2XYZ(@Lab, $wtpt); # array
$Lab = XYZ2Lab($XYZ, $wtpt); $XYZ = Lab2XYZ($Lab, $wtpt); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$XYZ = $chart->xyz([]); # get all XYZ data
# illuminant is D50 (default)
$Lab = XYZ2Lab($XYZ); # convert XYZ matrix to L*a*b* encoding
$XYZ_rt = Lab2XYZ($Lab); # convert back to XYZ encoding
$vector = XYZ2Lab($XYZ->[0]); # convert a vector
@array = XYZ2Lab(@{$XYZ->[0]}); # convert an array
# get F11 illuminant white point
$color = ICC::Support::Color->new({'illuminant' => 'F11'});
$wtpt = $color->iwtpt();
# illuminant is F11 (see note 1)
$Lab = XYZ2Lab($XYZ, $wtpt); # convert XYZ matrix to L*a*b* encoding
$XYZ_rt = Lab2XYZ($Lab, $wtpt); # convert back to XYZ encoding
$vector = XYZ2Lab($XYZ->[0], $wtpt); # convert a vector
@array = XYZ2Lab(@{$XYZ->[0]}, $wtpt); # convert an array
=over
=item 1
These L*a*b* values are computed per CIE 15. Be aware that the PCS for ICC profiles is always D50, and that non-D50 XYZ
values are transformed to D50 using a CAT (Chromatic Adaptation Transform) before converting to L*a*b*. See Annex E of the
ICC specification for an explanation. A CAT may be created directly using the ICC::Profile::matf module, or as a hash
option in ICC::Support::Chart.
=back
=head3 XYZ2Lxyz, Lxyz2XYZ
These functions convert between XYZ and Lxyz encoding.
B<Usage>
@Lxyz = XYZ2Lxyz(@XYZ); @XYZ = Lxyz2XYZ(@Lxyz); # array (D50)
$Lxyz = XYZ2Lxyz($XYZ); $XYZ = Lxyz2XYZ($Lxyz); # vector, matrix, array structure (D50)
@Lxyz = XYZ2Lxyz(@XYZ, $wtpt); @XYZ = Lxyz2XYZ(@Lxyz, $wtpt); # array
$Lxyz = XYZ2Lxyz($XYZ, $wtpt); $XYZ = Lxyz2XYZ($Lxyz, $wtpt); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$XYZ = $chart->xyz([]); # get all XYZ data
# illuminant is D50 (default)
$Lxyz = XYZ2Lxyz($XYZ); # convert XYZ matrix to Lxyz encoding
$XYZ_rt = Lxyz2XYZ($Lxyz); # convert back to XYZ encoding
$vector = XYZ2Lxyz($XYZ->[0]); # convert a vector
@array = XYZ2Lxyz(@{$XYZ->[0]}); # convert an array
# get F11 illuminant white point
$color = ICC::Support::Color->new({'illuminant' => 'F11'});
$wtpt = $color->iwtpt();
# illuminant is F11 (see note 1)
$Lxyz = XYZ2Lxyz($XYZ, $wtpt); # convert XYZ matrix to Lxyz encoding
$XYZ_rt = Lxyz2XYZ($Lxyz, $wtpt); # convert back to XYZ encoding
$vector = XYZ2Lxyz($XYZ->[0], $wtpt); # convert a vector
@array = XYZ2Lxyz(@{$XYZ->[0]}, $wtpt); # convert an array
=over
=item 1
These Lxyz values are computed per CIE 15. Be aware that the PCS for ICC profiles is always D50, and that non-D50 XYZ
values are transformed to D50 using a CAT (Chromatic Adaptation Transform) before converting to Lxyz. See Annex E of the
ICC specification for an explanation. A CAT may be created directly using the ICC::Profile::matf module, or as a hash
option in ICC::Support::Chart.
=back
=head3 XYZ2xyz, xyz2XYZ
These functions convert between XYZ and xyz encoding.
B<Usage>
@xyz = XYZ2xyz(@XYZ); @XYZ = xyz2XYZ(@xyz); # array (D50)
$xyz = XYZ2xyz($XYZ); $XYZ = xyz2XYZ($xyz); # vector, matrix, array structure (D50)
@xyz = XYZ2xyz(@XYZ, $wtpt); @XYZ = xyz2XYZ(@xyz, $wtpt); # array
$xyz = XYZ2xyz($XYZ, $wtpt); $XYZ = xyz2XYZ($xyz, $wtpt); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$XYZ = $chart->xyz([]); # get all XYZ data
# illuminant is D50 (default)
$xyz = XYZ2xyz($XYZ); # convert XYZ matrix to xyz encoding
$XYZ_rt = xyz2XYZ($xyz); # convert back to XYZ encoding
$vector = XYZ2xyz($XYZ->[0]); # convert a vector
@array = XYZ2xyz(@{$XYZ->[0]}); # convert an array
# get F11 illuminant white point
$color = ICC::Support::Color->new({'illuminant' => 'F11'});
$wtpt = $color->iwtpt();
# illuminant is F11 (see note 1)
$xyz = XYZ2xyz($XYZ, $wtpt); # convert XYZ matrix to xyz encoding
$XYZ_rt = xyz2XYZ($xyz, $wtpt); # convert back to XYZ encoding
$vector = XYZ2xyz($XYZ->[0], $wtpt); # convert a vector
@array = XYZ2xyz(@{$XYZ->[0]}, $wtpt); # convert an array
=over
=item 1
These xyz values are computed per CIE 15. Be aware that the PCS for ICC profiles is always D50, and that non-D50 XYZ
values are transformed to D50 using a CAT (Chromatic Adaptation Transform) before converting to xyz. See Annex E of the
ICC specification for an explanation. A CAT may be created directly using the ICC::Profile::matf module, or as a hash
option in ICC::Support::Chart.
=back
=head3 XYZ2xyY, xyY2XYZ
These functions convert between XYZ and xyY encoding. The x and y values are called chromaticity coordinates, and are often
shown on a chromaticity diagram. See L<https://en.wikipedia.org/wiki/File:CIE1931xy_blank.svg>.
B<Usage>
@xyY = XYZ2xyY(@XYZ); @XYZ = xyY2XYZ(@xyY); # array
$xyY = XYZ2xyY($XYZ); $XYZ = xyY2XYZ($xyY); # vector, matrix, array structure
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$XYZ = $chart->xyz([]); # get all XYZ data
$xyY = XYZ2xyY($XYZ); # convert XYZ matrix to xyY encoding
$XYZ_rt = xyY2XYZ($xyY); # convert back to XYZ encoding
$vector = XYZ2xyY($XYZ->[0]); # convert a vector
@array = XYZ2xyY(@{$XYZ->[0]}); # convert an array
=head3 x2L, L2x
These functions convert between linear and CIE L* encoding.
B<Usage>
$L = x2L($x); $x = L2x($L); # CIE L* function
B<Examples>
use ICC::Profile;
$chart = ICC::Support::Chart->new(''~/Desktop/GRACoL2006_Coated1_CGATS.txt'); # make a 'Chart' object
$xyz = $chart->xyz([], {'encoding' => 9}); # get all xyz data
$L = x2L($xyz->[99][1]); # compute L* value of sample 99
$y = L2x($L); # convert back to y value
=head3 dLdx, dxdL
These functions compute the derivatives of the CIE L* function and its inverse.
B<Usage>
$dLdx = dLdx($x); $dxdL = dxdL($L); derivative of CIE L* function
B<Examples>
=head3 xyz2Lab_jac, Lab2xyz_jac
These functions compute the Jacobian matrix of the C<xyz2Lab> and C<Lab2xyz> functions.
B<Usage>
$jac = xyz2Lab_jac($xyz); # Jacobian matrix of xyz2Lab function
$jac = Lab2xyz_jac($Lab); # Jacobian matrix of Lab2xyz function
B<Examples>
=head3 XYZ2W
This function computes the CIE Whiteness value.
B<Usage>
$W = XYZ2W(@XYZ, $wtpt); # CIE Whiteness
B<Examples>
=head3 xyz2dwv
This function computes the density weighted value.
B<Usage>
$dwv = xyz2dwv($xyz); # density weighted value
B<Examples>
=head2 Color difference functions
=head3 dEab
This function computes the CIE βE*ab color difference.
B<Usage>
$dE = dEab(@Lab1, @Lab2); # CIE βE*ab color difference
B<Examples>
=head3 dE94
This function computes the CIE βE94 color difference.
B<Usage>
$dE = dE94(@Lab1, @Lab2); # CIE βE94 color difference
B<Examples>
=head3 dE00
This function computes the CIE βE00 color difference.
B<Usage>
$dE = dE00(@Lab1, @Lab2); # CIE βE00 color difference
B<Examples>
=head3 dE99
This function computes the DIN99 color difference
B<Usage>
$dE = dE99(@Lab1, @Lab2); # DIN99 color difference
$dE = dE99(@Lab1, @Lab2, Ke, Kch); # DIN99 color difference
B<Examples>
=head3 dEcmc
This function computes the CMC(l:c) color difference.
B<Usage>
$dE = dEcmc(@Lab1, @Lab2); # CMC(l:c) color difference
$dE = dEcmc(@Lab1, @Lab2, l, c); # CMC(l:c) color difference
B<Examples>
=head3 dLCh
This function computes βL*, βCh, as used to determine G7 grayscale compliance
B<Usage>
($dL, $dCh) = dLCh(@Lab1, @Lab2); # βL*, βCh
B<Examples>
=head3 dLab
This function computes simple color differences, βL*, βa*, βb*
B<Usage>
($dL, $da, $db) = dLab(@Lab1, @Lab2);
B<Examples>
=head2 Illuminant functions
=head3 CCT
This function computes the correlated color temperature of an illuminant, and the black body error value.
B<Usage>
($cct, $err) = CCT($x, $y); # correlated color temperature
B<Examples>
=head3 CCT2
This function computes the correlated color temperature of an illuminant using McCamy's approximation.
B<Usage>
$cct = CCT2($x, $y); # correlated color temperature using McCamy's approximation
B<Examples>
=head3 bbrad
This function computes the black body radiance using Planck's law.
B<Usage>
$rad = bbrad($nm, $T); # black body radiance using Planck's law
B<Examples>
=head3 bbxy
This function computes the chromaticity of black body radiator.
B<Usage>
($x, $y) = bbxy($T); # chromaticity of black body radiator
B<Examples>
=head3 bbuv
This function computes the CIE UCS 1960 coordinates of black body radiator.
B<Usage>
($u, $v) = bbuv($T); CIE UCS 1960 of black body radiator
B<Examples>
=head3 XYZ2ucs
This function converts XYZ values to CIE UCS 1960 coordinates.
B<Usage>
($u, $v) = XYZ2ucs(@XYZ); # CIE UCS 1960
B<Examples>
=head3 xy2ucs
This function converts chromaticity values to CIE UCS 1960 coordinates.
B<Usage>
($u, $v) = xy2ucs(@xy); # CIE UCS 1960
B<Examples>
=head3 daylight
This function computes the SPD of CIE daylight at a given correlated color temperature.
B<Usage>
($range, $spd) = daylight($cct); range and SPD of daylight
B<Examples>
=head2 Interpolation functions
=head3 linear
This function interpolates a vector, using linear approximation.
B<Usage>
$vec_out = linear($vec_in, $range_in, $range_out); # interpolate a vector (linear)
B<Examples>
=head3 linear_matrix
This function computes an interpolation matrix, using linear approximation.
B<Usage>
$matrix = linear_matrix($range_in, $range_out); # make interpolating matrix (linear)
B<Examples>
=head3 cspline
This function interpolates a vector, using cubic spline approximation.
B<Usage>
$vec_out = cspline($vec_in, $range_in, $range_out); # interpolate a vector (natural cubic spline)
B<Examples>
=head3 cspline_matrix
This function computes an interpolation matrix, using cubic spline approximation.
B<Usage>
$matrix = cspline_matrix($range_in, $range_out); # make interpolating matrix (natural cubic spline)
B<Examples>
=head3 lagrange
This function interpolates a vector, using Lagrange approximation.
B<Usage>
$vec_out = lagrange($vec_in, $range_in, $range_out); # interpolate a vector (Lagrange, ASTM E 2022)
B<Examples>
=head3 lagrange_matrix
This function computes an interpolation matrix, using Lagrange approximation.
B<Usage>
$matrix = lagrange_matrix($range_in, $range_out); # make interpolating matrix (Lagrange, ASTM E 2022)
B<Examples>
=head2 Vector functions
=head3 dotProduct
This function computes the dot product of two vectors.
B<Usage>
$scalar = dotProduct($vec1, $vec2); # vector dot product
B<Examples>
=head3 crossProduct
This function computes the cross product of two vectors.
B<Usage>
$vector = crossProduct($vec1, $vec2); # vector cross product
B<Examples>
=head2 Utility functions
=head3 flatten
This function flattens an array structure.
B<Usage>
$vector = flatten($structure); # flatten an array structure
B<Examples>
=head3 clip_struct
This function clips all of the values within an array structure.
B<Usage>
clip_struct($structure); # clip each element of an array structure
B<Examples>
=head3 round
This function rounds off a value to the nearest integer.
B<Usage>
$integer = round($value); # round off value to nearest integer (+/-)
B<Examples>
=head3 s15f162v
This function converts a vector from ICC s15Fixed16Number encoding.
B<Usage>
$vector = s15f162v($s15f16); # convert from s15Fixed16Number vector
B<Examples>
=head3 v2s15f16
This function converts a vector to ICC s15Fixed16Number encoding.
B<Usage>
$s15f16 = v2s15f16($vector); # convert to s15Fixed16Number vector
B<Examples>
=head3 makeProfileFolder
This function makes a folder for saving ICC profiles.
B<Usage>
(profiles_folder_path, directory_segs, customer, job) = makeProfileFolder(file/folder_path); # make folder for profiles
(profiles_folder_path, directory_segs, customer, job) = makeProfileFolder(file/folder_path, alias_folder_path);
B<Examples>
=head3 getICCPath
This function gets the path to the 'ICC' distribution folder. The optional parameter is appended to the path.
B<Usage>
$path = getICCPath(); # get path to 'ICC' distribution folder
$path = getICCPath(sub_path); # get path to some item within the 'ICC' distribution folder
B<Examples>
$path = getICCPath(); # get path to 'ICC' folder
$path = getICCPath('Data'); # get path to 'ICC/Data' folder
$path = getICCPath('Data/ASTM_E308_data.yml'); # get path to 'ICC/Data/ASTM_E308_data.yml' file
=head3 filterPath
This function replaces a leading '~' with the user's home path.
For non-Windows OS, the '\' character (escape) is removed. For Windows OS, '/' character is replaced by '\'.
B<Usage>
filterPath($path);
B<Examples>
$path = '~/Desktop/test.txt';
filterPath($path);
print "$path\n";
$path = 'name\ with\ spaces.txt';
filterPath($path);
print "$path\n";
=head3 setFile
This function sets Mac OSX creator and file type.
B<Usage>
setFile(path_to_file, creator, type); # set Mac OSX creator and file type (deprecated by Apple)
B<Examples>
=head3 parse_tokens
This function splits a string of tokens, and parses any parameters using the 'eval' function.
It provides a convenient user interface for selecting an assortment of items, with optional
parameters. The parameters can be any valid Perl expression, including scalars, anonymous
arrays, and anonymous hashes. Expressions may also contain functions and global variables.
The function returns an array reference. The array contains the tokens, interspersed with the
evaluated parameters. A parameter group may contain more than one parameter. So, each group is
an array reference. See the example below.
B<Usage>
$array_ref = parse_tokens($token_string);
B<Examples>
$tokens = parse_tokens("option1, option2(25), option3([1, 2, 3]), option4({'key' => 99})");
print Dumper($tokens);
produces this output,
$VAR1 = [
'option1',
'option2',
[
25
],
'option3',
[
[
1,
2,
3
]
],
'option4',
[
{
'key' => 99
}
]
];
=head2 Parameter testing functions
=head3 is_vector
This function tests if the parameter is a vector. Elements may be numeric or undef.
B<Usage>
$flag = is_vector($vec); # test if parameter is a vector
B<Examples>
print is_vector([]); # true
print is_vector({}); # false
print is_vector([1, 2, 3]); # true
print is_vector([undef, 2, 3]); # true
print is_vector(['xxx', 2, 3]); # false
=head3 is_num_vector
This function tests if the parameter is a vector. Elements must be numeric.
B<Usage>
$flag = is_num_vector($vec); # test if parameter is a vector
B<Examples>
print is_num_vector([]); # true
print is_num_vector({}); # false
print is_num_vector([1, 2, 3]); # true
print is_num_vector([undef, 2, 3]); # false
print is_num_vector(['xxx', 2, 3]); # false
=head3 is_matrix
This function tests if the parameter is a matrix. Elements may be numeric or undef.
B<Usage>
$flag = is_matrix($mat); # test if parameter is a matrix
B<Examples>
print is_matrix([]); # true
print is_matrix({}); # false
print is_matrix([[]]); # true
print is_num_matrix([{}]); # false
print is_matrix([[1, 2, 3]]); # true
print is_matrix(Math::Matrix->new([1, 2, 3])); # true
print is_matrix([[undef, 2, 3]]); # true
print is_matrix([['xxx', 2, 3]]); # false
=head3 is_num_matrix
This function tests if the parameter is a matrix. Elements must be numeric.
B<Usage>
$flag = is_num_matrix($mat); # test if parameter is a matrix
B<Examples>
print is_num_matrix([]); # true
print is_num_matrix({}); # false
print is_num_matrix([[]]); # true
print is_num_matrix([{}]); # false
print is_num_matrix([[1, 2, 3]]); # true
print is_num_matrix(Math::Matrix->new([1, 2, 3])); # true
print is_num_matrix([[undef, 2, 3]]); # false
print is_num_matrix([['xxx', 2, 3]]); # false
=head1 CONSTANTS
=head2 Perl handling of constants
Perl's C<constant> pragma is used to make the following constants. These are actually subroutines, created at compile time.
Their values cannot be altered, so they are effectively constants. Because they are subroutines, there are no sigils, which
occasionally leads to ambiguity. This can be resolved by enclosing the constant in parentheses (see example below).
=head3 D50
D50 illuminant XYZ values, as specified by the ICC (based on the CIE 1931 2 degree observer)
Note that the ICC values for D50 ([96.42, 100, 82.49]) are slightly different from the CIE values ([96.42, 100, 82.51]).
B<Examples>
$XYZ = D50; # vector
$Z = D50->[2]; # Z value
@XYZ = @{(D50)}; # array, note the parentheses
@XYZ = Lab2XYZ(@Lab, D50); # use as white point to change encoding
=head3 d50
D50 illuminant XYZ values, encoded as 32-bit ICC XYZNumber, [0.9624, 1, 0.8249].
=head3 d50P
D50 illuminant XYZ values, encoded as 16-bit ICC XYZ, approximately [0.48211, 0.50001, 0.41246].
=head3 PI
circumference of a unit circle, approximately 3.14159
=head3 radian
degrees in a radian, approximately 57.29578
=head3 ln10
natural logarithm of 10, approximately 2.30258
=head1 SEE ALSO
=head2 ASTM Standards
B<ASTM E 2022> I<Standard Practice for Calculation of Weighting Factors for Tristimulus Integration>
=head2 CIE Standards
B<CIE 15> I<Colorimetry>
=head2 DIN Standards
B<DIN 6176> I<Colorimetric evaluation of colour differences of surface colours according to DIN99 formula>
=head2 ICC Specification
The ICC (International Color Consortium) maintains a web site at L<http://www.color.org>
The ICC specification and related materials may be downloaded from this web site.
The ICC specification is also published as ISO 15076-1.
=head2 ISO Standards
B<ISO 15076-1> I<Image technology colour management β Architecture, profile format and data structure β Part 1: Based on ICC.1:2010>
=head1 LICENSE
Programs in this distribution, authored by William B. Birkett, are licensed under the GNU General Public License, v3.
See L<https://www.gnu.org/licenses/gpl-3.0.html> for license details.
=head1 AUTHOR
William B. Birkett, E<lt>wbirkett@doplganger.comE<gt>
=head1 COPYRIGHT
Copyright E<0x00A9> 2004-2019 by William B. Birkett
=cut