vaab / colour

Python color representations manipulation library (RGB, HSL, web, ...)
BSD 2-Clause "Simplified" License
319 stars 41 forks source link

lightness based color range when using black or white #49

Open gtrombi opened 5 years ago

gtrombi commented 5 years ago

Thanks for this library, it's very cool and useful. Maybe you could add another kind of range in order to make gradients, e.g. now the color range from blue to white is "passing" through other colors, like green, while it would be nice to have also the opportunity to make a gradient from blue to white which is just making the blue paler and paler until white, so basically it would be a lightness based range.

asciipip commented 3 years ago

Here's what I think is going on, in a bit more detail.

Color.range_to() works in HSL space. But the colour library treats any color with a saturation of zero as also having a hue of zero. (In many contexts, this makes sense. Color(hsl=(0, 0, 0.5)) and Color(hsl=(0.5, 0, 0.5)) both refer to the exact same color, so clamping the hue to zero make for unambiguous canonical representations.) So gradients to or from unsaturated colors end up going through a lot of unexpected hues.

e.g.

>>> for c in Color('#00F').range_to(Color('#FFF'), 4):
...   print(c.hsl)
... 
(0.6666666666666666, 1.0, 0.5)
(0.4444444444444444, 0.6666666666666667, 0.6666666666666666)
(0.2222222222222222, 0.33333333333333337, 0.8333333333333333)
(0.0, 0.0, 1.0)

This happens even if you try to explicitly fudge the hue.

>>> for c in Color(hsl=(0.66, 1, 0.5)).range_to(Color(hsl=(0.66, 0, 1)), 4):
...   print(c.hsl)
... 
(0.66, 1.0, 0.5)
(0.44000000000000006, 0.6666666666666667, 0.6666666666666666)
(0.22000000000000003, 0.33333333333333337, 0.8333333333333333)
(0.0, 0.0, 1.0)

For those examples, I would, instead, expect to see the following sequence of colors:

(0.66, 1.0, 0.5)
(0.66, 0.66, 0.66)
(0.66, 0.33, 0.83)
(0.66, 0.0, 1.0)

(The final one could also be (0.0, 0.0, 1.0).)

I think that Color.range_to() should have a special case if at least one endpoint has a saturation of zero. In that case, it should maintain the hue from the nonzero-saturation endpoint and only vary the saturation and lightness as it steps from one end to the other.