summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/color_engine.py49
-rw-r--r--src/instant_rice.py30
-rw-r--r--src/paths.py6
-rw-r--r--src/update_i3.py58
-rw-r--r--src/update_polybar.py24
-rw-r--r--src/update_rofi.py23
-rw-r--r--src/user_interface.py51
7 files changed, 241 insertions, 0 deletions
diff --git a/src/color_engine.py b/src/color_engine.py
new file mode 100644
index 0000000..f86b2e7
--- /dev/null
+++ b/src/color_engine.py
@@ -0,0 +1,49 @@
+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 rgbToHex(input_values: 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):
+ hex_value = hex_value.lstrip('#')
+ return tuple(int(hex_value[i:i+2], 16) for i in (0, 2, 4))
+
+def compColors(color_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]
+ compliments.append('#' + ''.join(comp))
+ return compliments
+
diff --git a/src/instant_rice.py b/src/instant_rice.py
new file mode 100644
index 0000000..87c9968
--- /dev/null
+++ b/src/instant_rice.py
@@ -0,0 +1,30 @@
+import sys
+import color_engine
+import user_interface
+import update_rofi
+import update_i3
+import update_polybar
+from paths import Paths
+
+def main():
+ if '-r' in sys.argv:
+ img_path = user_interface.pickRandomWallpaper()
+ else:
+ img_path = sys.argv[1]
+
+ hex_colors, hex_compliments = user_interface.colorPickerUI(img_path)
+ if 'polybar' in Paths:
+ update_polybar.updatePolybarTheme(Paths['polybar'], hex_colors, hex_compliments)
+ if 'rofi' in Paths:
+ update_rofi.updateRofiTheme(Paths['rofi'], hex_colors, hex_compliments)
+ if 'i3' in Paths:
+ update_dmenu = True if ('-dmenu' in sys.argv) else False
+ if '--nolock' in sys.argv:
+ update_i3.updatei3Theme(Paths['i3'], img_path, hex_colors, hex_compliments, False, update_dmenu)
+ else:
+ update_i3.updatei3Theme(Paths['i3'], img_path, hex_colors, hex_compliments, True, update_dmenu)
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/src/paths.py b/src/paths.py
new file mode 100644
index 0000000..7ad287b
--- /dev/null
+++ b/src/paths.py
@@ -0,0 +1,6 @@
+Paths = {
+ 'i3': '/home/chandler/.config/i3/config',
+ 'polybar': '/home/chandler/.config/polybar/config.ini',
+ 'wallpapers': '/home/chandler/Pictures/papes/',
+ 'lockscreen': '/home/chandler/.config/i3/'
+ }
diff --git a/src/update_i3.py b/src/update_i3.py
new file mode 100644
index 0000000..6430f6e
--- /dev/null
+++ b/src/update_i3.py
@@ -0,0 +1,58 @@
+import subprocess
+import cv2 as cv
+import os
+
+from rich import print
+from paths import Paths
+
+def updatei3Theme(config_path: str, img_path: str, colors: list, compliments: list, lock: bool, dmenu: bool):
+ print('[bold red]Updating i3 color scheme')
+ data = ''
+ with open(config_path, 'r') as file:
+ data = file.readlines()
+
+ for i, line in enumerate(data):
+ # update colors
+ if "set $bgcolor" in line:
+ data[i] = 'set $bgcolor ' + colors[0] + '\n'
+ if "set $in-bgcolor" in line:
+ data[i] = 'set $in-bgcolor ' + colors[1] + '\n'
+ if "set $text" in line:
+ data[i] = 'set $text ' + compliments[0] + '\n'
+ if "set $indicator" in line:
+ data[i] = 'set $indicator ' + colors[2] + '\n'
+ if "set $in-text" in line:
+ data[i] = 'set $in-text ' + compliments[1] + '\n'
+ #update background image
+ if "set $bgimage" in line:
+ data[i] = 'set $bgimage ' + img_path + '\n'
+
+ if "bindsym $mod+d exec --no-startup-id dmenu_run" in line:
+ if dmenu:
+ print('[bold red]Updating Dmenu color scheme')
+ data[i] = f"bindsym $mod+d exec --no-startup-id dmenu_run -nb '{colors[0]}' -sf '{compliments[0]}' -sb '{colors[1]}' -nf '{compliments[1]}'\n"
+ # update i3lock image, convert to png so it plays nice w i3lock
+ if lock:
+ img = cv.imread(img_path)
+ imgHeight, imgWidth, _ = img.shape
+ screenWidth, screenHeight = getScreenResolution()
+ lock_scale = screenWidth / imgWidth
+ print('[bold red]Creating lock screen')
+ dim = (int(imgWidth * lock_scale), int(imgHeight * lock_scale))
+ img = cv.resize(img, dim, interpolation= cv.INTER_AREA)
+ cv.imwrite('lock.png', img)
+ os.rename('lock.png', Paths['lockscreen'] + 'lock.png')
+ with open(config_path, 'w') as file:
+ file.writelines(data)
+
+ print("[bold red]Restarting i3")
+ os.system("i3 restart")
+
+
+def getScreenResolution():
+ output = subprocess.Popen('xrandr | grep "\*" | cut -d" " -f4',shell=True, stdout=subprocess.PIPE).communicate()[0]
+ resolution = output.split()[0].split(b'x')
+ width = int(resolution[0].decode('UTF-8'))
+ height = int(resolution[1].decode('UTF-8'))
+ return width, height
+
diff --git a/src/update_polybar.py b/src/update_polybar.py
new file mode 100644
index 0000000..ff395c6
--- /dev/null
+++ b/src/update_polybar.py
@@ -0,0 +1,24 @@
+
+
+def updatePolybarTheme(config_path: str, colors: list, compliments: list):
+ print('[bold red]Updating polybar color scheme')
+ data = ''
+ with open(config_path, 'r') as file:
+ data = file.readlines()
+ for i,line in enumerate(data):
+ #update colors
+ if "background =" in line and i == 19:
+ data[i] = 'background = ' + colors[0] + '\n'
+ if "background-alt =" in line and i == 20:
+ data[i] = 'background-alt = ' + colors[1] + '\n'
+ if "foreground =" in line and i == 21:
+ data[i] = 'foreground = ' + compliments[0] + '\n'
+ if "primary =" in line and i == 22:
+ data[i] = 'primary = ' + compliments[1] + '\n'
+ if "secondary =" in line and i == 23:
+ data[i] = 'secondary = ' + compliments[2] + '\n'
+ if "disabled =" in line and i == 25:
+ data[i] = 'disabled = ' + colors[2] + '\n'
+ with open(config_path, 'w') as file:
+ file.writelines(data)
+
diff --git a/src/update_rofi.py b/src/update_rofi.py
new file mode 100644
index 0000000..a7d3aa6
--- /dev/null
+++ b/src/update_rofi.py
@@ -0,0 +1,23 @@
+import color_engine
+
+def updateRofiTheme(config_path: str, colors: list, compliments: list):
+ print('[bold red]Updating Rofi color scheme')
+ data = ''
+ with open(config_path, 'r') as file:
+ data = file.readlines()
+ bg = color_engine.hexToRGB(colors[1])
+ fg = color_engine.hexToRGB(compliments[1])
+ lbg = color_engine.hexToRGB(colors[0])
+ lfg = color_engine.hexToRGB(colors[0])
+ for i,line in enumerate(data):
+ if 'background: ' in line and i == 23:
+ data[i] = ' background: rgba({}, {}, {}, 70%);\n'.format(bg[0], bg[1], bg[2])
+ if 'foreground: ' in line and i == 28:
+ data[i] = ' foreground: rgba({}, {}, {}, 100%);\n'.format(fg[0], fg[1], fg[2])
+ if 'lightbg: ' in line and i == 12:
+ data[i] = ' lightbg: rgba({}, {}, {}, 100%);\n'.format(lbg[0], lbg[1], lgb[2])
+ if 'lightfg: ' in line and i == 7:
+ data[i] = ' lightfg: rgba({}, {}, {}, 100%);\n'.format(lfg[0], lfg[1], lfg[2])
+ with open(config_path, 'w') as file:
+ file.writelines(data)
+
diff --git a/src/user_interface.py b/src/user_interface.py
new file mode 100644
index 0000000..32abf60
--- /dev/null
+++ b/src/user_interface.py
@@ -0,0 +1,51 @@
+import os
+import random
+from paths import Paths
+import color_engine
+from rich import print
+
+
+def colorPickerUI(img_path: str):
+#display the selected color scheme and ask user if they like it or want to generate a new color scheme
+ confirmed = False
+ while not confirmed:
+ print()
+ popularColors = color_engine.grabColors(img_path, 3)
+ hex_colors = color_engine.rgbToHex(popularColors)
+ hex_compliments = color_engine.compColors(hex_colors)
+
+ main_colors = ''
+ complimentary_colors = ''
+
+ for color in hex_colors:
+ main_colors += f'[on {color}] [/on {color}]'
+ print(main_colors)
+ for color in hex_compliments:
+ complimentary_colors += f'[on {color}] [/on {color}]'
+ print(complimentary_colors)
+ print()
+ count = 0
+ for i in range(len(hex_colors)):
+ print(f'[{hex_compliments[i]} on {hex_colors[i]}]\tGenerated Color Scheme\t\t ({count})')
+ count += 1
+ print('[bold](a)ccept (r)etry')
+ response = input('> ')
+ if response == 'r':
+ continue
+ else:
+ confirmed = True
+ return hex_colors, hex_compliments
+
+def pickRandomWallpaper():
+ confirmed = False
+ while not confirmed:
+ wallpaper = Paths['wallpapers'] + random.choice(os.listdir(Paths['wallpapers']))
+ os.system(f'viu {wallpaper}')
+ print(f'picked wallpaper: {wallpaper}')
+ print('[bold](a)ccept (r)etry')
+ response = input('>')
+
+ if response == 'a':
+ confirmed = True
+
+ return wallpaper