ICC-Profile
view release on metacpan or search on metacpan
lib/ICC/Shared.pm view on Meta::CPAN
$derv = ($errx - $err)/1E-3;
# initialize delta T
$dT = $derv > 0 ? -2 : 2;
# optimization loop
for (0 .. 30) {
# adjust T value
$T += $dT;
# compute current u,v values
($u, $v) = bbuv($T);
# compute current error
$err = sqrt(($u - $ut)**2 + ($v - $vt)**2);
# compute delta values
($ux, $vx) = bbuv($T + 1E-3);
# compute delta error
$errx = sqrt(($ux - $ut)**2 + ($vx - $vt)**2);
# save previous derr/dT values
$derv0 = $derv;
# compute new derr/dT
$derv = ($errx - $err)/1E-3;
# quit loop if derr/dT < 1E-9
last if (abs($derv) < 1E-9);
# adjust delta T if sign of derivative changes
$dT /= -2 if (($derv > 0) ^ ($derv0 > 0));
}
# return CCT
return($T, $err);
}
# correlated color temperature (CCT)
# using McCamy's approximation
# parameters: (x, y)
# returns: (CCT)
sub CCT2 {
# get parameters
my ($x, $y) = @_;
# compute n
my $n = ($x - 0.3320)/($y - 0.1858);
# return CCT
return(-449 * $n**3 + 3525 * $n**2 - 6823.3 * $n + 5520.33);
}
# black body radiance (Planck's law)
# using constants and formula per CIE 15
# wavelength in nm, temperature in degrees Kelvin
# parameters: (wavelength, temperature)
# returns: (radiance)
sub bbrad {
# get parameters
my ($lambda, $T) = @_;
# CIE constants
my $c1 = 3.741771E-16; # 2Ïhc²
my $c2 = 1.4388E-2; # hc/kB
# convert wavelength to meters
$lambda *= 1E-9;
# return radiance value
return($c1/(PI * $lambda**5 * (exp($c2/($lambda * $T)) - 1)));
}
# compute chromaticity values of black body radiator
# parameter: (temperature)
# returns: (x, y)
sub bbxy {
# get temperature
my $T = shift();
# local variables
my ($b, $X, $Y, $Z, $d);
# load CIE color matching functions (YAML format)
state $cmf = YAML::Tiny->read(getICCPath('Data/CIE_cmfs_360-830_x_1.yml'))->[0];
# for each wavelength (360 - 830 nm)
for my $i (0 .. 470) {
# compute black body reflectance
$b->[$i] = bbrad($i + 360, $T);
}
# compute colorimetry
$X = dotProduct($cmf->{'CIE1931x'}, $b);
$Y = dotProduct($cmf->{'CIE1931y'}, $b);
$Z = dotProduct($cmf->{'CIE1931z'}, $b);
# compute denominator
($d = $X + $Y + $Z) || croak('X + Y + Z = 0 when computing chromaticity');
# return x,y
return($X/$d, $Y/$d);
}
# compute UCS 1960 values of black body radiator
# parameter: (temperature)
# returns: (u, v)
sub bbuv {
( run in 1.143 second using v1.01-cache-2.11-cpan-5735350b133 )