The truth is rarely pure and never simple

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 ./ 4 ff0000 00ff00
You get:     ,     ,      and     
You want four additional colors ./ 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]

def parse_color(input):
    rgb = [0]*3
    if input.startswith('#'):
        offset = 1
        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)
        raise ValueError('Unable to parse input')
    return tuple(rgb)

got = []
    [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]
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.