summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChandler J <cjustice2000@gmail.com>2024-03-02 12:39:36 -0700
committerChandler J <cjustice2000@gmail.com>2024-03-02 12:39:36 -0700
commit2c98c5fe81cd649a6ae66dd3ed295f1cb2f46849 (patch)
treefce5790659b300d64f1b1bbdb93ea0dfb10cd69e /src
parentb956fdd8cd5a4dc0620d02d0f981e507a4ee85e5 (diff)
improved color picking procedure
Diffstat (limited to 'src')
-rw-r--r--src/color_engine.py71
-rw-r--r--src/get_args.py13
-rw-r--r--src/instant_rice.py6
-rw-r--r--src/load_config.py13
-rw-r--r--src/paths.py7
-rw-r--r--src/user_interface.py58
6 files changed, 119 insertions, 49 deletions
diff --git a/src/color_engine.py b/src/color_engine.py
index 1b94a02..fb885a8 100644
--- a/src/color_engine.py
+++ b/src/color_engine.py
@@ -10,7 +10,6 @@ def grabColors(img_path: str, num_colors: int) -> list():
"""
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)
@@ -20,6 +19,58 @@ def grabColors(img_path: str, num_colors: int) -> list():
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
@@ -39,16 +90,10 @@ def hexToRGB(hex_value: str) -> tuple:
hex_value = hex_value.lstrip('#')
return tuple(int(hex_value[i:i+2], 16) for i in (0, 2, 4)) # Magic :DDDDDD
-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 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
diff --git a/src/get_args.py b/src/get_args.py
index 09c5279..ade7740 100644
--- a/src/get_args.py
+++ b/src/get_args.py
@@ -1,27 +1,20 @@
import user_interface
import os
-def get_args(args) -> tuple:
+def get_args(args, walls_dir) -> tuple:
# arguments that can be passed into program
- dmenu = False
- nolock = False
initialize = False
reconfigure = False
- nolock = False
if '-r' in args:
- img_path = user_interface.pickRandomWallpaper()
+ img_path = user_interface.pickRandomWallpaper(walls_dir)
else:
img_path = f"{os.getcwd()}/{args[1]}"
if '--initialize' in args:
initialize = True
if '--reconfigure' in args:
reconfigure = True
- if '--dmenu' in args:
- dmenu = True
- if '--nolock' in args:
- nolock = True
- return img_path, dmenu, nolock, initialize, reconfigure
+ return img_path, initialize, reconfigure
def usage(args) -> None:
print(f"""
diff --git a/src/instant_rice.py b/src/instant_rice.py
index a42ec0f..5076a6b 100644
--- a/src/instant_rice.py
+++ b/src/instant_rice.py
@@ -9,14 +9,14 @@ from load_config import systemConfig
if __name__ == '__main__':
if len(sys.argv) > 1:
- img_path, update_dmenu, nolock, initialize, reconfigure = get_args(sys.argv)
- hex_colors, hex_compliments = user_interface.colorPickerUI(img_path)
config = systemConfig()
+ img_path, initialize, reconfigure = get_args(sys.argv, config.wallpaper_directory)
+ hex_colors, hex_compliments = user_interface.colorPickerUI(img_path, config.num_palettes)
if config.polybar_config != "":
update_polybar.updatePolybarTheme(config.polybar_config, hex_colors, hex_compliments)
if config.rofi_config != "":
update_rofi.updateRofiTheme(config.rofi_config, hex_colors, hex_compliments)
if config.i3_config:
- update_i3.updatei3Theme(config.i3_config, img_path, hex_colors, hex_compliments, nolock, config.use_dmenu, config.i3_lock_image)
+ update_i3.updatei3Theme(config.i3_config, img_path, hex_colors, hex_compliments, config.generate_i3_lock, config.use_dmenu, config.i3_lock_image)
else:
usage(sys.argv)
diff --git a/src/load_config.py b/src/load_config.py
index 2c894a3..dbc0d81 100644
--- a/src/load_config.py
+++ b/src/load_config.py
@@ -16,8 +16,8 @@ class systemConfig:
rofi_config = ""
username = ""
rice_config = ""
-
#instant rice configuration settings
+ num_palettes = 15
use_dmenu = False
generate_i3_lock = False
@@ -69,5 +69,14 @@ class systemConfig:
match = line.split(' ')
self.generate_i3_lock = True if match[2] == 'True' else False
if "wallpaper_directory" in line:
- match = line.split(' ')
+ match = line.strip().split(' ')
+ if not match[2].endswith('/'):
+ match[2] += '/'
self.wallpaper_directory = match[2]
+ if "num_palettes" in line:
+ match = line.strip().split(' ')
+ if match[2].isdigit():
+ self.num_palettes = int(match[2])
+ else:
+ print(f'Invalid configuration parameter at line {i}:\n{line}.\nUsing default \
+ configuration of 15 palettes.')
diff --git a/src/paths.py b/src/paths.py
deleted file mode 100644
index b4cf3d5..0000000
--- a/src/paths.py
+++ /dev/null
@@ -1,7 +0,0 @@
-Paths = {
- 'i3': '/home/chandler/.config/i3/config',
- 'polybar': '/home/chandler/.config/polybar/config.ini',
- 'wallpapers': '/home/chandler/Pictures/papes/',
- 'lockscreen': '/home/chandler/.config/i3/',
- 'rofi': '/home/chandler/.config/rofi/theme.rasi'
- }
diff --git a/src/user_interface.py b/src/user_interface.py
index f3d068a..12014a6 100644
--- a/src/user_interface.py
+++ b/src/user_interface.py
@@ -1,19 +1,25 @@
import os
import random
-from paths import Paths
+
import color_engine
from rich import print
-def colorPickerUI(img_path: str) -> tuple:
+def colorPickerUI(img_path: str, num_palettes: int) -> tuple:
#display the selected color scheme and ask user if they like it or want to generate a new color scheme
+ hex_colors, hex_compliments = selectPalette(img_path, num_palettes)
+ final_colors, final_compliments = selectColorsFromPalette(hex_colors, hex_compliments)
+ return final_colors, final_compliments
+
+def selectPalette(img_path: str, num_palettes: int) -> tuple:
+ #
confirmed = False
while not confirmed:
print()
- popularColors = color_engine.grabColors(img_path, 3)
+ popularColors = color_engine.grabColors(img_path, num_palettes)
hex_colors = color_engine.rgbToHex(popularColors)
hex_compliments = color_engine.compColors(hex_colors)
-
+ constrast_levels = color_engine.checkContrast(hex_colors, hex_compliments)
main_colors = ''
complimentary_colors = ''
@@ -22,29 +28,53 @@ def colorPickerUI(img_path: str) -> tuple:
print(main_colors)
for color in hex_compliments:
complimentary_colors += f'[on {color}] [/on {color}]'
- print(complimentary_colors)
- print()
+ print(complimentary_colors, '\n')
count = 0
for i in range(len(hex_colors)):
- print(f'[{hex_compliments[i]} on {hex_colors[i]}]\tGenerated Color Scheme\t\t ({count})')
+ print(f'[{hex_compliments[i]} on {hex_colors[i]}]\tGenerated Color Scheme\t\t ({count})', f'contrast: {constrast_levels[i]}')
count += 1
- print('[bold](a)ccept (r)etry')
+ print('[bold](a)ccept palette (g)enerate new palette')
response = input('> ')
- if response == 'r':
- continue
- else:
+ if response == 'a':
confirmed = True
+ print('[bold green]Palette Confirmed!')
+ else:
+ continue
+
return hex_colors, hex_compliments
-def pickRandomWallpaper() -> str:
+def selectColorsFromPalette(hex_colors, hex_compliments):
+ selected = False
+ while not selected:
+ print('[bold blue]Select top 3 colors from list in order Primary, Secondary, Accent (IE, "4 10 6")')
+ selectedColors = input("> ")
+ selectedColors = selectedColors.split()
+ all_digits = all(i.isdigit() for i in selectedColors)
+ if all_digits:
+ selected = True
+ else:
+ print('[bold red]Invalid selection. Use positive integers corresponding to color pair to select.')
+ continue
+
+ selectedColors = [int(i) for i in selectedColors]
+ final_colors = []
+ final_compliments = []
+
+ for selection in selectedColors:
+ final_colors.append(hex_colors[selection])
+ final_compliments.append(hex_compliments[selection])
+
+ return final_colors, final_compliments
+
+def pickRandomWallpaper(walls_dir) -> str:
confirmed = False
history = []
- num_wallpapers = len(os.listdir(Paths['wallpapers']))
+ num_wallpapers = len(os.listdir(walls_dir))
while not confirmed:
if len(history) == num_wallpapers:
print('[bold blue] Wallpapers exhausted. Resetting history...')
history.clear()
- wallpaper = Paths['wallpapers'] + random.choice(os.listdir(Paths['wallpapers']))
+ wallpaper = walls_dir + random.choice(os.listdir(walls_dir))
if wallpaper in history:
continue
history.append(wallpaper)