summaryrefslogtreecommitdiff
path: root/src/color_engine.py
blob: 504e84bf1db3822dd559eb2469aef9aacc9b66ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import cv2 as cv
from sklearn.cluster import KMeans

def grabColors(img_path: str, num_colors: int) -> list:
    """
    Takes in an image, and Number of colors, then returns a list of those colors.
    The list of colors will contain the most prominent colors present in the image.
    img_path - the path where your image lives (IE, /home/chandler/Pictures/moss.png)
    num_colors - the number of colors you need back from the image
    """
    img = cv.imread(img_path)
    img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    # scale image down by factor of 10 to decrease computation time
    dim = (int(len(img[0])/10), int(len(img)/10))
    img = cv.resize(img, dim, interpolation= cv.INTER_AREA)
    clt = KMeans(n_clusters=num_colors, n_init='auto')
    clt.fit(img.reshape(-1, 3))
    return clt.cluster_centers_

def compColors(color_list: list) -> list:
    """
    given a list of colors, generate complimentary colors to contrast the prominent colors.
    return a list of these colors.
    """
    compliments = []
    for color in color_list:
        curr_hex = color[1:] 
        rgb = (curr_hex[0:2], curr_hex[2:4], curr_hex[4:6])
        comp = ['%02X' % (255 - int(a, 16)) for a in rgb]
        compliments.append('#' + ''.join(comp))
    return compliments

def checkContrast(hex_color_list: list, hex_compliment_list: list) -> list:
    """
    Given the list of colors and their compliments, reutrn a list of the contrast values
    between the colors
    """
    color_list = hexToRGB_list(hex_color_list)
    compliment_list = hexToRGB_list(hex_compliment_list)
    contrast_values = []

    for i, color in enumerate(color_list):
        compliment = compliment_list[i]

        # determine relative luminance of each color
        color_luminence = relativeLuminance(color)
        compliment_luminence = relativeLuminance(compliment)
        value = (max(color_luminence, compliment_luminence) + 0.05) / (min(color_luminence, compliment_luminence) + 0.05)
        contrast_values.append(value)
    return contrast_values



def relativeLuminance(color: list) -> float:
    """
    Determines the luminance of color. The luminance allows us to
    compute the contrast between two colors by comparing their
    relative luminance.

    The magic constants in this function are all taken from the following
    description of relative luminance:
    https://www.w3.org/TR/WCAG20/#relativeluminancedef
    """ 
    threshold = 0.03928 
    channels = []

    for channel in color:
        channel_norm = channel / 255
        if channel_norm <= threshold:
            channels.append(channel_norm / 12.92)
        else:
            channel_val = ((channel_norm + 0.055) / 1.055)**(2.4)
            channels.append(channel_val)
    
    red, green, blue = channels
    luminance = (0.2126 * red) + (0.7152 * green) + (0.0722 * blue)
    return luminance
    

def rgbToHex(input_values: list) -> list:
    """
    Takes in a list of RBG color values and returns a list of those same colors as hex values
    """
    hex_list=[]
    for color in input_values:
        red = int(color[0])
        green = int(color[1])
        blue = int(color[2])
        hex_list.append('#{:02x}{:02x}{:02x}'.format(red, green, blue))
    return hex_list


def hexToRGB(hex_value: str) -> tuple:
    """
    Takes in a list of Hex values and returns a tuple of those colors as rgb values
    """
    hex_value = hex_value.lstrip('#')
    return tuple(int(hex_value[i:i+2], 16) for i in (0, 2, 4)) 


def hexToRGB_list(hex_list: list) -> list:
    colors = []
    for color in hex_list:
        hex_value = color.lstrip('#')
        colors.append(tuple(int(hex_value[i:i+2], 16) for i in (0, 2, 4))) 
    return colors