facelessuser / coloraide

A library to aid in using colors
https://facelessuser.github.io/coloraide
MIT License
195 stars 12 forks source link

Possibly extend Robertson 1968 CCT to 1000K #326

Closed facelessuser closed 1 year ago

facelessuser commented 1 year ago

We've been able to replicate the calculations to generate the 31 points (with corrections as noted here http://www.brucelindbloom.com/index.html?Math.html). With this, we have full confidence that we can generate the original table values and values above and beyond the original 31 points with the same accuracy and consistency. We could even generate them at higher precision, higher resolution, etc.

With all of that said, we will likely generate the 31 points as documented to provide a faithful version, but possibly with the one expectation that we may extend the low range to 1000K. We've already made some adjustments to the algorithm to handle the change in slope that occurs in very low wavelengths (slope changing from negative to positive). We just need to make one more change to accommodate changes in slope in relation to Duv

facelessuser commented 1 year ago

The differences are noted below. Everything is the same except we now have points to guide the curve through 1667K - 1000K and it now looks like it should.

original extended

facelessuser commented 1 year ago

I'm thinking this may be a nice way to unify the two offerings we have. It faithfully implements the documented range, but also extends it and would align both approaches to operate between 1000K - 100000K. Robertson will be faster, but less accurate, but maybe make sense to be the default due to its speed and it is decent enough for general purposes. Technically, Robertson will give you a range out to infinity but the accuracy drops more and more as you approach infinity.

Ohno can be used for times when more accuracy is required. While we've improved the performance, it will be slower, than Robertson.

To be honest, Robertson can have its accuracy greatly improved by increasing data point resolution, much like how we extended its range to 1000K. We can leave this up to the user, as they can actually pass in their own tables if desired, even tables built off other CMFs. More precision could also be provided for values in the table, so we have a bit of flexibility for custom approaches and improvements.

facelessuser commented 1 year ago

Table comparison. We round to the same significant figures, this could be dropped, but to implement a faithful reproduction it was necessary.

Original:

[  (0.0, 0.18006, 0.26352, -0.24341),
   (10.0, 0.18066, 0.26589, -0.25479),
   (20.0, 0.18133, 0.26846, -0.26876),
   (30.0, 0.18208, 0.27119, -0.28539),
   (40.0, 0.18293, 0.27407, -0.30470),
   (50.0, 0.18388, 0.27709, -0.32675),
   (60.0, 0.18494, 0.28021, -0.35156),
   (70.0, 0.18611, 0.28342, -0.37915),
   (80.0, 0.18740, 0.28668, -0.40955),
   (90.0, 0.18880, 0.28997, -0.44278),
   (100.0, 0.19032, 0.29326, -0.47888),
   (125.0, 0.19462, 0.30141, -0.58204),
   (150.0, 0.19962, 0.30921, -0.70471),
   (175.0, 0.20525, 0.31647, -0.84901),
   (200.0, 0.21142, 0.32312, -1.0182),
   (225.0, 0.21807, 0.32909, -1.2168),
   (250.0, 0.22511, 0.33439, -1.4512),
   (275.0, 0.23247, 0.33904, -1.7298),
   (300.0, 0.24010, 0.34308, -2.0637),
   (325.0, 0.24792, 0.34655, -2.4681),  # Note: 0.24792 is a corrected value for the error found in W&S as 0.24702
   (350.0, 0.25591, 0.34951, -2.9641),
   (375.0, 0.26400, 0.35200, -3.5814),
   (400.0, 0.27218, 0.35407, -4.3633),
   (425.0, 0.28039, 0.35577, -5.3762),
   (450.0, 0.28863, 0.35714, -6.7262),
   (475.0, 0.29685, 0.35823, -8.5955),
   (500.0, 0.30505, 0.35907, -11.324),
   (525.0, 0.31320, 0.35968, -15.628),
   (550.0, 0.32129, 0.36011, -23.325),
   (575.0, 0.32931, 0.36038, -40.770),
   (600.0, 0.33724, 0.36051, -116.45)]

Calculated (and extended)

[   (0.0, 0.18006, 0.26352, -0.24341),
    (10.0, 0.18066, 0.26589, -0.25479),
    (20.0, 0.18133, 0.26846, -0.26876),
    (30.0, 0.18208, 0.27119, -0.28539),
    (40.0, 0.18293, 0.27407, -0.3047),
    (50.0, 0.18388, 0.27709, -0.32675),
    (60.0, 0.18494, 0.28021, -0.35156),
    (70.0, 0.18611, 0.28342, -0.37915),
    (80.0, 0.1874, 0.28668, -0.40955),
    (90.0, 0.1888, 0.28997, -0.44278),
    (100.0, 0.19032, 0.29326, -0.47888),
    (125.0, 0.19462, 0.30141, -0.58204),
    (150.0, 0.19962, 0.30921, -0.70471),
    (175.0, 0.20525, 0.31647, -0.84901),
    (200.0, 0.21142, 0.32312, -1.0182),
    (225.0, 0.21807, 0.32909, -1.2168),
    (250.0, 0.22511, 0.33439, -1.4512),
    (275.0, 0.23247, 0.33904, -1.7298),
    (300.0, 0.2401, 0.34308, -2.0637),
    (325.0, 0.24792, 0.34655, -2.4681),
    (350.0, 0.25591, 0.34951, -2.9641),
    (375.0, 0.264, 0.352, -3.5814),
    (400.0, 0.27218, 0.35407, -4.3633),
    (425.0, 0.28039, 0.35577, -5.3762),
    (450.0, 0.28863, 0.35714, -6.7262),
    (475.0, 0.29685, 0.35823, -8.5955),
    (500.0, 0.30505, 0.35907, -11.324),
    (525.0, 0.3132, 0.35968, -15.628),
    (550.0, 0.32129, 0.36011, -23.325),
    (575.0, 0.32931, 0.36038, -40.77),
    (600.0, 0.33724, 0.36051, -116.45),
    # Extended values beyond this point
    (625.0, 0.34508, 0.36053, 189.78),
    (650.0, 0.35281, 0.36044, 57.748),
    (675.0, 0.36044, 0.36026, 35.979),
    (700.0, 0.36795, 0.36002, 27.095),
    (725.0, 0.37535, 0.35972, 22.303),
    (750.0, 0.38262, 0.35937, 19.328),
    (775.0, 0.38976, 0.35897, 17.318),
    (800.0, 0.39677, 0.35855, 15.879),
    (825.0, 0.40366, 0.3581, 14.807),
    (850.0, 0.4104, 0.35763, 13.985),
    (875.0, 0.41701, 0.35715, 13.339),
    (900.0, 0.42349, 0.35665, 12.822),
    (925.0, 0.42983, 0.35615, 12.403),
    (950.0, 0.43603, 0.35564, 12.059),
    (975.0, 0.44209, 0.35513, 11.773),
    (1000.0, 0.44801, 0.35462, 11.535)]
facelessuser commented 1 year ago

We have a draft pull up. Our approach is pretty dynamic, so this allows you to use the Robertson method with other CMFs if desired:

from coloraide.temperature import robertson_1968
from coloraide import cmfs
from coloraide import cat

class Custom(Color):
    ...

Custom.register(
    robertson_1968.Robertson1968(cmfs.cie_1964_10deg, cat.WHITES['10deg']['D65']),
    overwrite=True
 )