generate distinguishable colors

Sometimes you have some colors and need different ones based on distinguishability. No, I’m not talking about matching colors, just different ones. Here is an example:

You have:      and     
You want four additional colors ./colordist.py 4 ff0000 00ff00
You get:     ,     ,      and     
You want four additional colors ./colordist.py 4 ff0000 00ff00 00ffcb 0065ff 6600ff ff00cb
You get:     ,     ,      and     

#!/usr/bin/env python
import colorsys, sys, math

if len(sys.argv) < 3:
    print 'Usage: %s amount color1 [color2, color3]\nAll colors as hexadecimal numbers using RGB colorspace.' % sys.argv[0]
    exit(1)

def parse_color(input):
    rgb = [0]*3
    if input.startswith('#'):
        offset = 1
    else:
        offset = 0
    if len(input)-offset == 6:
        rgb[0] = int(input[offset+0:offset+2], 16)/float(255)
        rgb[1] = int(input[offset+2:offset+4], 16)/float(255)
        rgb[2] = int(input[offset+4:offset+6], 16)/float(255)
    else:
        raise ValueError('Unable to parse input')
    return tuple(rgb)

got = []
try:
    [got.append(colorsys.rgb_to_hsv(*parse_color(colorcode))) for colorcode in sys.argv[2:]]
except ValueError:
    print 'Unable to parse input'

s = sum([color[1] for color in got])/len(got)
v = sum([color[2] for color in got])/len(got)

hval = [color[0] for color in got]
hval.append(hval[0]+1)
hval.sort()
maxdiff = 0
pos = -1
for i in range(len(hval)-1):
    diff = hval[i+1]-hval[i]
    if diff > maxdiff:
        pos = i
        maxdiff = diff

amount = int(sys.argv[1])
maxdiff /= (amount + 1)
for i in range(amount):
    newcolor = (int(math.floor(cval*255)) for cval in colorsys.hsv_to_rgb(hval[pos]+(i+1)*maxdiff, s, v))
    print '#{0:02x}{1:02x}{2:02x}'.format(*newcolor)

Technical note: The basic idea of the solution is the conversion of the RGB input colors to the HSL colorspace and using the H of HSL in order to find the output colors. The whole process has no notion of the human color perception.

Leave a comment

Your email address will not be published.