Generate color list between two colors in HSV


Lets say i have two RGB colors (255,0,0) and (0,0,255), I also require 100 colors that are between them. How would i generate a list of HSV color values based on a number of required steps?

Currently using python 3 i created this code:

def lerpcolourhsv(rgb1, rgb2, steps):
#convert rgb to hsv
hsv1 = colorsys.rgb_to_hsv(rgb1[0], rgb1[1], rgb1[2])
hsv2 = colorsys.rgb_to_hsv(rgb2[0], rgb2[1], rgb2[2])

# calculate distance between two hue numbers, divide by number of steps. then loop to generate
rgb_colour_list = []
dist = cachefunc.numdistance(hsv1[0], hsv2[0])
step_value = dist / steps
hue = hsv1[0]

for x in range(steps):
    hsv_tupel = (hue, 1, 1)
    hue += step_value
    rgb = colorsys.hsv_to_rgb(hsv_tupel[0], hsv_tupel[1], hsv_tupel[2])
    rgb = (round(rgb[0] * 255), round(rgb[1] * 255), round(rgb[2] * 255), round(255)) #0-1 to 0-255
    rgb_colour_list.append(rgb)

return rgb_colour_list

The only problem with the code above is that it loops through multiple different colors for example: red -> orange -> yellow -> green -> cyan -> blue

I would like a function that instead produces results more similar to this: red to blue color gradient

As can be seen, this gradient produces a more expected result of red -> purple -> blue

I tried making a function that interpolates using individual rgb channel values, this gave a more similar result however the perceived brightness and saturation of the colors were off so i am trying to do this in hsv color space.

Can anyone create a function or explain how to achieve the gradient above using the hsv color space?


Answers:


It sounds like you want to create a gradient across the RGB colorspace rather than across the hue. And your problem is that you wrote a bunch of code to convert it to HSV so you can gradient across the hue and convert it back? If so, the answer is simple: don't write that code; just stick with RGB.

Since you haven't given us a complete example, I can't show you exactly how to change your code, but here's a simple version:

r1, g1, b1 = rgb1
r2, g2, b2 = rgb2
rdelta, gdelta, bdelta = (r2-r1)/steps, (g2-g1)/steps, (b2-b1)/steps
for step in range(steps):
    r1 += rdelta
    g1 += gdelta
    b1 += bdelta
    output.append((r1, g1, b1))

So, for example, because g1 and g2 are both 0, none of your output colors will include any green, which I think is what you're after.

(Of course if you're using numpy arrays, the whole thing is even simpler—you can just operate on rows as 2D arrays of RGB columns, and replace the whole loop with a single call to linspace.)