If the hue component of my HSL color is in degrees, how can I correctly interpolate between two hues? Using (h1 + h2) / 2 does not seem to produce desirable results in all cases. Here are two examples that illustrate why:
Let:
red = 0°
yellow = 60°
blue = 240°
(red + yellow) / 2 = 30° (orange)
(yellow + blue) / 2 = 150° (blue green)
(red + blue) / 2 = 120° (green)
As you can see, averaging red and blue produces green instead purple/magenta! However, if we let:
red = 360°
yellow = 60°
blue = 240°
(red + yellow) / 2 = 210° (blue green)
(yellow + blue) / 2 = 150° (blue green)
(red + blue) / 2 = 300° (magenta)
Now, red and blue produce the expected color, but red and yellow produce a blue green color! In what way can I interpolate the hue component of the color so that the result matches what would be expected of mixing actual paint? Thanks!
You're basically doing this right to get what I assume you want, which is a color that looks midrange between your two inputs, but you just need to deal with the fact that this calculation is done on a circle which wraps. (I assume that you don't really want "mixing like paint" but just a midrange color -- i.e. you don't want red and green to give brown, right?)
Here's a Python function that will pick the angle between two angles on a circle. It basically just tries the two options (adding 360 or not) and picks the one that gives the angle closest to the original angles:
pairs = [(0, 60), (60, 239), (60, 241), (0, 240), (350, 30)]
def circ_ave(a0, a1):
r = (a0+a1)/2., ((a0+a1+360)/2.)%360
if min(abs(a1-r[0]), abs(a0-r[0])) < min(abs(a0-r[1]), abs(a1-r[1])):
return r[0]
else:
return r[1]
for a0, a1 in pairs:
print a0, a1, circ_ave(a0, a1)
produces:
0 60 30.0
60 239 149.5 # 60, 240 is ambiguous
60 241 330.5
0 240 300.0
350 30 10.0
(I feel there should be an easier way to do this calculation, but it didn't occur to me.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With