facelessuser / coloraide

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

Allow specifying CIE Lab space for CIE Lab based distancing algorithms #361

Closed facelessuser closed 1 year ago

facelessuser commented 1 year ago

The provided CIE Lab based distancing algorithms (∆E 76, 94, 2000, and CMC) all calculate distancing relative to the points within the Lab color space used. For instance color(--lab 20 -3 40) and color(--lab 70 -30 4) evaluated in lab would yield the same results as color(--lab-d65 20 -3 40) and color(--lab-d65 70 -30 4) in lab-d65. But red and blue would not yield the same results if evaluated in lab and then in lab-d65.

We currently use Lab D65 as the default color space for the above distancing algorithms, and frankly, there is nothing wrong with that. D65 is the main color space used in ColorAide. Relying on D65 prevents us from wasting time chromatically adapting colors every time we want to calculate the distance. This means things are a little bit faster.

On the other hand, a lot of people expect distancing to be in Lab D50. This is still very common in the print industry.

We need a way to allow people use either D50 or D65, or better put, any CIE Lab compatible color space. People may want to use Lab D65 with 10˚ standard observer. To enable this, the user needs to the option to clarify what CIE Lab they want to use.

To do this, we need to differentiate CIE Lab color spaces from generic Lab-Like spaces. To do this, Lab D50 and Lab D65 need to be derived from a special CIELab class. We can go ahead and do this for CIE LCh as well. Then, ∆E 76, 94, 2000, and CMC all need to throw an error if the provided space is not derived from CIELab as a non-CIELab space will give wildly bad results as they are not designed for other Lab-like spaces.

Then we can do something like the following to explicitly specify the Lab color space to use:

Color('red').delta_e('blue', method='2000', cielab='lab')
Color('red').delta_e('blue', method='2000', cielab='lab-d65')

We can probably allow specifying a specific default if someone always want to use one or the other. By default, we will continue with lab-d65, but I could see someone doing what is shown below to make a D50 Lab the default. We would just need to be explicit internally if we absolutely needed to use a specific approach.

from coloraide import Color as Base
from coloraide.distance.delta_e_2000 import DE2000

class Color(Base): ...

Color.register(DE2000(cielab='lab'), overwrite=True)