Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating the analogous color with python

Tags:

python

colors

If I had RGB values: 255, 165, 0, what could be done to calculate the analogous color(s) of 218, 255, 0 and 255, 37, 0, but still applying for any RGB color?

For example:

>>> to_analogous(0, 218, 255)
[(0, 255, 165),(0, 90, 255)]

EDIT: For simplicity, an analogous color can be viewed as this, green being the input color, then the blue green and yellow green being the output:

(source: tigercolor.com)

like image 660
Hairr Avatar asked Dec 30 '12 23:12

Hairr


1 Answers

Converting from RGB to HSL and rotating +/- 30 degrees might be indeed what you want, but you will not get the color wheel showed. Obtaining, respectively, 12 and 128 colors, starting with pure red (at top), this is what you will get:

enter image description hereenter image description here

And here is sample code to produce the analogous colors:

import colorsys

DEG30 = 30/360.
def adjacent_colors((r, g, b), d=DEG30): # Assumption: r, g, b in [0, 255]
    r, g, b = map(lambda x: x/255., [r, g, b]) # Convert to [0, 1]
    h, l, s = colorsys.rgb_to_hls(r, g, b)     # RGB -> HLS
    h = [(h+d) % 1 for d in (-d, d)]           # Rotation by d
    adjacent = [map(lambda x: int(round(x*255)), colorsys.hls_to_rgb(hi, l, s))
            for hi in h] # H'LS -> new RGB
    return adjacent

The other color wheel was obtained by considering a subtractive color system. For that, let us consider the RYB color space for simplicity (it represents the color mixing you probably learned in your art classes in any typical school). By using it, we immediately obtain the following wheels:

enter image description hereenter image description here

To obtain these analogous colors, we consider a color in RGB to directly represent a color in RYB, and then convert from RYB to RGB. For example, suppose you have a triple (255, 128, 0) in RGB. Call that triple a RYB triple and convert to RGB to obtain (255, 64, 0). This RYB -> RGB conversion is not unique in the sense that there might be multiple definitions for it, I've used the one from "Paint Inspired Color Compositing" by Gosset and Chen. Here is the code to perform the conversion:

def _cubic(t, a, b):
    weight = t * t * (3 - 2*t)
    return a + weight * (b - a)

def ryb_to_rgb(r, y, b): # Assumption: r, y, b in [0, 1]
    # red
    x0, x1 = _cubic(b, 1.0, 0.163), _cubic(b, 1.0, 0.0)
    x2, x3 = _cubic(b, 1.0, 0.5), _cubic(b, 1.0, 0.2)
    y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
    red = _cubic(r, y0, y1)

    # green
    x0, x1 = _cubic(b, 1.0, 0.373), _cubic(b, 1.0, 0.66)
    x2, x3 = _cubic(b, 0., 0.), _cubic(b, 0.5, 0.094)
    y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
    green = _cubic(r, y0, y1)

    # blue
    x0, x1 = _cubic(b, 1.0, 0.6), _cubic(b, 0.0, 0.2)
    x2, x3 = _cubic(b, 0.0, 0.5), _cubic(b, 0.0, 0.0)
    y0, y1 = _cubic(y, x0, x1), _cubic(y, x2, x3)
    blue = _cubic(r, y0, y1)

    return (red, green, blue)
like image 162
mmgp Avatar answered Nov 11 '22 11:11

mmgp