Open LBdN opened 7 years ago
Can you check what hue have your start and end color ? Can you reproduce it in python interactive shell and copy paste here for reproduction ?
ok, I dig a bit and the case is more rare than I thought. It doesn't happen from a normal gradient. It does happen when the end color of the gradient is a very dark version of the start color. I use the following code to transform one into the other :
def light_color(color, percentage, darken ):
color = Color(color)
if darken:
new_lum = ( 1 - percentage/100.0) * color.luminance
else:
new_lum = ( 1 + percentage/100.0) * color.luminance
color.luminance = max(min(new_lum,1), 0)
return {"color" : [color]}
If the darkening percentage is very high, I get this kind of result :
in the console, I have this result :
Engine inputs
Engine 0: [<Color #df1c50>]
Engine results
Engine color:[<Color black>]
May I share with you a few hints that might help us find the culprit...
in the current version of Color (in master branch, tag 0.1.4), the Color object will store the HSL value only and will do all the conversion for set/get any attributes. so:
.hsl
or .hue
, .saturation
, .luminance
are actually direct access to internal stored data.colour
(namely .range_to(..)
method and color_scale(..)
function) are using HSL format internally also.In HSL, it is the .hue
value that will give you the color of the object in the rainbow. Focusing on this attribute should show you a changing hue if you notice changing in color. Note that hue is a cyclic value: 0 is equal to 1.
.range_to(..)
or color_scale(..)
means you'll ask to span hue across 0-1, which means you'll want to go through all colors..luminance
should only make a fixed color brighter. At 0 it is all dark (it is black for all colors), and at 1 it is all light (white for all colors). This mean that you can have a black red and a black blue for instance that are both black (aka #000 in RGB). In that sense, HSL to RGB is not a bijection. On your last message, it is not clear for me if the image you pasted is the result of using .range_to(..)
(or color_scale(..)
or if it is your code that was used to get this result. In the latter case, this is indeed quite a bit puzzling.
To go forward on this topic, I'll suggest you to:
.hue
value in debugging logsMany thanks for your interest in colour
. If you have time also, you might want to check out this branch that is sketching the future of Colour
: #31 ... I still need some reviews that it doesn't break anything.
I just came across this! Sorry if this is an older issue, but I have some code to reproduce:
from colour import Color
start = Color("#da0000")
print("start HSL: " + str(start.hsl))
end = Color("#7a0009")
print("end HSL: " + str(end.hsl))
for color in list(start.range_to(end, 10)):
print(color.hsl)
start HSL: (0.0, 1.0, 0.42745098039215684)
end HSL: (0.9877049180327868, 1.0, 0.23921568627450981)
(0.0, 1.0, 0.42745098039215684)
(0.10974499089253187, 1.0, 0.4065359477124183)
(0.21948998178506374, 1.0, 0.3856209150326797)
(0.3292349726775956, 1.0, 0.36470588235294116)
(0.4389799635701275, 1.0, 0.3437908496732026)
(0.5487249544626593, 1.0, 0.32287581699346407)
(0.6584699453551912, 1.0, 0.3019607843137255)
(0.7682149362477231, 1.0, 0.28104575163398693)
(0.877959927140255, 1.0, 0.2601307189542484)
(0.9877049180327868, 1.0, 0.23921568627450984)
It's a red to a sort of dark red, but we go through the whole hue range before we end back up a little shifted from where we started. I think it's due to the wrapping at 0/360. Hue isn't linear, it's circle so the color_scale
function might need to be more complex to handle that.
This rainbow type effect might be desired behavior for some, I would have liked to take the shortest path however. I could see this being implemented as a flag like force_shortest=True
or something as to not break existing functionality but to allow crossing that hue border.
colour version 0.1.5
Hi @vaab, I solved the pb on my cython version, so you can try on your end. Note the color instance returned by the delta method is the shortest distance in the color space between self and other. It is not really a valid color, more a delta hence the name. But it serves it purpose correctly. :)
cpdef add(self, Color other):
cdef float h = self.h + other.h
if (h < <float>0): h += <float>1
if (h > <float>1): h -= <float>1
return Color(
h = h,
s = self.s + other.s,
l = self.l + other.l,
a = self.a + other.a,
temp = True
)
cpdef delta(self, Color other):
cdef float d1 = self.h - other.h
cdef float d2_sign = 1 if d1 < 0 else -1
cdef float d2 = <float>1.0 - abs(d1)
cdef float d
if abs(d2) < abs(d1):
d = d2_sign * d2
else:
d = d1
return Color(
h = d,
s = self.s - other.s,
l = self.l - other.l,
a = self.a - other.a,
temp = True
)
When building a gradient from a color to black, the gradient go through many other hues, instead of going simply darker. It looks quite unnatural. Wouldn't it be possible to treat white and black as special cases ?