38

I want to generate a list of color specifications in the form of (r, g, b) tuples, that span the entire color spectrum with as many entries as I want. So for 5 entries I would want something like:

  • (0, 0, 1)
  • (0, 1, 0)
  • (1, 0, 0)
  • (1, 0.5, 1)
  • (0, 0, 0.5)

Of course, if there are more entries than combination of 0 and 1 it should turn to use fractions, etc. What would be the best way to do this?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Sverre Rabbelier
  • 1,456
  • 2
  • 16
  • 22

5 Answers5

62

Use the HSV/HSB/HSL color space (three names for more or less the same thing). Generate N tuples equally spread in hue space, then just convert them to RGB.

Sample code:

import colorsys
N = 5
HSV_tuples = [(x*1.0/N, 0.5, 0.5) for x in range(N)]
RGB_tuples = map(lambda x: colorsys.hsv_to_rgb(*x), HSV_tuples)
kquinn
  • 10,433
  • 4
  • 35
  • 35
  • 3
    Cool, then using colorsys.hsv_to_rgb I get exactly what I need :). [colorsys.hsv_to_rgb(x*1.0/N, 0.5, 0.5) for x in range(N)]. – Sverre Rabbelier May 18 '09 at 09:46
  • 2
    if you want to use an index in `RGB_tuples`, in Python 3 you must make a `list` out of the `map`, which is a generator, simply by `list(map(lambda...))` – Walter Tross Oct 19 '19 at 09:38
  • 2
    in Python 3 you don't need `x*1.0/N`, `x/N` always produces a float result. To get an integer result you would need to do `x//N` – Walter Tross Oct 19 '19 at 11:04
  • those `0.5`s can be replaced by other values. HSV tuples are (hue, saturation, value) tuples, with all tuple elements in the range from 0 to 1, see https://en.wikipedia.org/wiki/HSL_and_HSV – Walter Tross Oct 19 '19 at 11:09
41

Color palettes are interesting. Did you know that the same brightness of, say, green, is perceived more intensely than, say, red? Have a look at http://poynton.ca/PDFs/ColorFAQ.pdf. If you would like to use preconfigured palettes, have a look at seaborn's palettes:

import seaborn as sns
palette = sns.color_palette(None, 3)

Generates 3 colors from the current palette.

serv-inc
  • 35,772
  • 9
  • 166
  • 188
  • 1
    IMHO this is better than the accepted answer because the colors in the palette are distinctive. The HSV method generates colors that are hard to tell apart. – Björn Lindqvist Nov 26 '19 at 23:02
  • 1
    Yes, I 100% agree! This is much more modular and concise than the method presented in the accepted answer. – Shounak Ray Aug 05 '20 at 16:01
  • The palettes generated by Seaborn look great. I just wish it didn't depend on Matplotlib, which is a beast. – Martin CR Dec 06 '20 at 10:50
  • 1
    An entire paper on nothing but color theory, but not a single color in the entire article! Impresive. – Sebastian Nov 26 '21 at 11:20
14

Following the steps of kquinn's and jhrf :)

For Python 3 it can be done the following way:

def get_N_HexCol(N=5):
    HSV_tuples = [(x * 1.0 / N, 0.5, 0.5) for x in range(N)]
    hex_out = []
    for rgb in HSV_tuples:
        rgb = map(lambda x: int(x * 255), colorsys.hsv_to_rgb(*rgb))
        hex_out.append('#%02x%02x%02x' % tuple(rgb))
    return hex_out
ceprio
  • 373
  • 3
  • 10
12

I created the following function based on kquinn's answer.

from colorsys import hsv_to_rgb
    
def get_hex_color_list(num_colors=5, saturation=1.0, value=1.0):
    hex_colors = []
    hsv_colors = [[float(x / num_colors), saturation, value] for x in range(num_colors)]
    
    for hsv in hsv_colors:
       hsv = [int(x * 255) for x in hsv_to_rgb(*hsv)]
    
       # Formatted as hexadecimal string using the ':02x' format specifier
       hex_colors.append(f"#{hsv[0]:02x}{hsv[1]:02x}{hsv[2]:02x}")
    
    return hex_colors
MrE
  • 19,584
  • 12
  • 87
  • 105
jhrf
  • 980
  • 9
  • 17
  • I was searching for this (y). But in my case there was no much light after I saw adding them to form a spectrum. The output looks like this [Spectrum](https://postimg.org/image/qspiz6c4h/) I need to have some more brightness on it. – ln2khanal Aug 05 '16 at 14:55
  • The hsv space is hue, saturation, value, so a saturation closer to 1 will make stronger colours and a value closer to 1 will higher the brightness. – C.Fe. Jun 22 '17 at 08:24
  • 1
    Anybody know the best way to update this to Py3? Something like: `hex_out.append("".join(list(map(lambda x: chr(x)[2:], rgb))))`? – kuanb Aug 12 '17 at 16:56
4

However many number of colors you need and very simple.

from matplotlib import cm
n_colors = 10
colours = cm.rainbow(np.linspace(0, 1, n_colors))
momo668
  • 199
  • 3
  • 8