Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HSL Interpolation

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!


1 Answers

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.)

like image 152
tom10 Avatar answered Nov 28 '25 03:11

tom10



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!