How to interpolate hue values in HSV colour space? How to interpolate hue values in HSV colour space? javascript javascript

How to interpolate hue values in HSV colour space?


You should just need to find out which is the shortest path from starting hue to ending hue. This can be done easily since hue values range from 0 to 255.

You can first subtract the lower hue from the higher one, then add 256 to the lower one to check again the difference with swapped operands.

int maxCCW = higherHue - lowerHue;int maxCW = (lowerHue+256) - higherHue;

So you'll obtain two values, the greater one decides if you should go clockwise or counterclockwise. Then you'll have to find a way to make the interpolation operate on modulo 256 of the hue, so if you are interpolating from 246 to 20 if the coefficient is >= 0.5f you should reset hue to 0 (since it reaches 256 and hue = hue%256 in any case).

Actually if you don't care about hue while interpolating over the 0 but just apply modulo operator after calculating the new hue it should work anyway.


Although this answer is late, the accepted one is incorrect in stating that hue should be within [0, 255]; also more justice can be done with clearer explanation and code.

Hue is an angular value in the interval [0, 360); a full circle where 0 = 360. The HSV colour space is easier to visualize and is more intuitive to humans then RGB. HSV forms a cylinder from which a slice is shown in many colour pickers, while RGB is really a cube and isn't really a good choice for a colour picker; most ones which do use it would have to employ more sliders than required for a HSV picker.

The requirement when interpolating hue is that the smaller arc is chosen to reach from one hue to another. So given two hue values, there are four possibilities, given with example angles below:

Δ |  ≤ 180  |  > 180--|---------|---------+ |  40, 60 | 310, 10− |  60, 40 | 10, 310if Δ = 180 then both +/− rotation are valid options

Lets take + as counter-clockwise and as clockwise rotation. If the difference in absolute value exceeds 180 then normalize it by ± 360 to make sure the magnitude is within 180; this also reverses the direction, rightly.

var d = h2 - h1;var delta = d + ((Math.abs(d) > 180) ? ((d < 0) ? 360 : -360) : 0);

Now just divide delta by the required number of steps to get the weight of each loop iteration to add to the start angle during interpolating.

var new_angle = start + (i * delta);

Relevant function excerpted from the complete code that follows:

function interpolate(h1, h2, steps) {  var d = h2 - h1;  var delta = (d + ((Math.abs(d) > 180) ? ((d < 0) ? 360 : -360) : 0)) / (steps + 1.0);  var turns = [];  for (var i = 1; d && i <= steps; ++i)    turns.push(((h1 + (delta * i)) + 360) % 360);  return turns;}