fromXyzInViewingConditions static method
Cam16
fromXyzInViewingConditions(
- double x,
- double y,
- double z,
- ViewingConditions viewingConditions,
Given color expressed in XYZ and viewed in viewingConditions, convert to
CAM16.
Implementation
static Cam16 fromXyzInViewingConditions(double x, double y, double z, ViewingConditions viewingConditions) {
// Transform XYZ to 'cone'/'rgb' responses
final double rC = 0.401288 * x + 0.650173 * y - 0.051461 * z;
final double gC = -0.250268 * x + 1.204414 * y + 0.045854 * z;
final double bC = -0.002079 * x + 0.048952 * y + 0.953127 * z;
// Discount illuminant
final double rD = viewingConditions.rgbD[0] * rC;
final double gD = viewingConditions.rgbD[1] * gC;
final double bD = viewingConditions.rgbD[2] * bC;
// chromatic adaptation
final double rAF = math.pow(viewingConditions.fl * rD.abs() / 100.0, 0.42).toDouble();
final double gAF = math.pow(viewingConditions.fl * gD.abs() / 100.0, 0.42).toDouble();
final double bAF = math.pow(viewingConditions.fl * bD.abs() / 100.0, 0.42).toDouble();
final double rA = MathUtils.signum(rD) * 400.0 * rAF / (rAF + 27.13);
final double gA = MathUtils.signum(gD) * 400.0 * gAF / (gAF + 27.13);
final double bA = MathUtils.signum(bD) * 400.0 * bAF / (bAF + 27.13);
// redness-greenness
final double a = (11.0 * rA + -12.0 * gA + bA) / 11.0;
// yellowness-blueness
final double b = (rA + gA - 2.0 * bA) / 9.0;
// auxiliary components
final double u = (20.0 * rA + 20.0 * gA + 21.0 * bA) / 20.0;
final double p2 = (40.0 * rA + 20.0 * gA + bA) / 20.0;
// hue
final double atan2 = math.atan2(b, a);
final double atanDegrees = atan2 * 180.0 / math.pi;
final double hue = MathUtils.sanitizeDegreesDouble(atanDegrees);
final double hueRadians = hue * math.pi / 180.0;
assert(hue >= 0 && hue < 360, 'hue was really $hue');
// achromatic response to color
final double ac = p2 * viewingConditions.nbb;
// CAM16 lightness and brightness
final double J = 100.0 * math.pow(ac / viewingConditions.aw, viewingConditions.c * viewingConditions.z);
final double Q =
(4.0 / viewingConditions.c) * math.sqrt(J / 100.0) * (viewingConditions.aw + 4.0) * (viewingConditions.fLRoot);
final double huePrime = (hue < 20.14) ? hue + 360 : hue;
final double eHue = (1.0 / 4.0) * (math.cos(huePrime * math.pi / 180.0 + 2.0) + 3.8);
final double p1 = 50000.0 / 13.0 * eHue * viewingConditions.nC * viewingConditions.ncb;
final double t = p1 * math.sqrt(a * a + b * b) / (u + 0.305);
final num alpha =
math.pow(t, 0.9) * math.pow(1.64 - math.pow(0.29, viewingConditions.backgroundYTowhitePointY), 0.73);
// CAM16 chroma, colorfulness, chroma
final double C = alpha * math.sqrt(J / 100.0);
final double M = C * viewingConditions.fLRoot;
final double s = 50.0 * math.sqrt((alpha * viewingConditions.c) / (viewingConditions.aw + 4.0));
// CAM16-UCS components
final double jstar = (1.0 + 100.0 * 0.007) * J / (1.0 + 0.007 * J);
final double mstar = math.log(1.0 + 0.0228 * M) / 0.0228;
final double astar = mstar * math.cos(hueRadians);
final double bstar = mstar * math.sin(hueRadians);
return Cam16(hue, C, J, Q, M, s, jstar, astar, bstar);
}