summaryrefslogtreecommitdiff
path: root/src/color_engine.py
blob: 0e43475ea49f3291523e118727f63ef246117cb7 (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
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)
    # TODO: implement KMeans clustering from scratch to
    # improve program modularity
    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:] # slice off the # from the hex code
        rgb = (curr_hex[0:2], curr_hex[2:4], curr_hex[4:6])
        comp = ['%02X' % (255 - int(a, 16)) for a in rgb] # magic :D
        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):
    
    threshold = 0.03928 # this whole function is magic constants lol
    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)) # Magic :DDDDDD

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))) # Magic :DDDDDD
    return colors