aboutsummaryrefslogtreecommitdiff
path: root/scripts/.local/bin/personal/tcolorget
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/.local/bin/personal/tcolorget')
-rwxr-xr-xscripts/.local/bin/personal/tcolorget125
1 files changed, 125 insertions, 0 deletions
diff --git a/scripts/.local/bin/personal/tcolorget b/scripts/.local/bin/personal/tcolorget
new file mode 100755
index 0000000..e3a478a
--- /dev/null
+++ b/scripts/.local/bin/personal/tcolorget
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+
+# A script to generate a color palette from an image which still complies with the
+# general terminal colors (i.e. red remains red).
+#
+# Author: David 'davidpkj' Penkowoj <davidpenkow1@gmail.com>
+# Version: 0.1.0
+# License: EUPL v. 1.2 @ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
+
+from PIL import Image
+from colour import Color
+
+import sys
+import math
+import colorz as clz
+import seaborn as sns
+import matplotlib.pyplot as plt
+
+# Rotate hue and saturation to get other colors
+def rotate(input):
+ # TODO: instead of rotation, maybe calculate deviation from standard value (i.e. hue 60, sat 50)
+ # and then apply the same deviation to all standard colors
+ # TODO: also do something about these arbitrary factors
+ result = []
+ iterations = 6
+ sat_factor = -0.1
+ hue_factor = 1 / iterations
+
+ for i in range(iterations):
+ _hue = input.hue
+ _sat = input.saturation
+ _lum = input.luminance
+
+ _hue = _hue + i * hue_factor
+ _hue = _hue - math.floor(_hue)
+
+ _newsat = _sat + abs(i * sat_factor)
+
+ if _newsat <= 1 and _newsat >= 0:
+ _sat = _newsat
+
+ result.append(Color(hsl=(_hue, _sat, _lum)))
+
+ return sorted(result, key=lambda x: x.hue)
+
+# Get the distance between two numbers (context: hue)
+def get_distance(color, target):
+ return abs(color.hue - target)
+
+# Returns the color which is closes in hue to the given value
+def select_nearest(value, colors):
+ target = value / 360
+ color = colors[0]
+ distance = get_distance(color, target)
+
+ for c in colors:
+ new_distance = get_distance(c, target)
+
+ if new_distance < distance:
+ color = c
+ distance = new_distance
+
+ # NOTE: special case for red, since can be numerically closer to
+ # 0° or 360° (1) but not the other. not nice but works
+ if target == 0:
+ new_color, new_distance = select_nearest(360, colors)
+
+ if new_distance < distance:
+ color = new_color
+
+ return color, distance
+
+# Show a palette
+def show_palette(colors):
+ sns.palplot(sns.color_palette(colors))
+ plt.show()
+
+# Save the original image with the attached palette back to disk.
+def save_image(colors, path):
+ palette_size = 30
+ input = Image.open(path)
+ colors_len = len(colors)
+
+ output = Image.new("RGB", (input.size[0], input.size[1] + palette_size), (0, 0, 0))
+ p2 = (input.size[0], input.size[1] + palette_size)
+
+ # Attaches the colors at the bottom of the image
+ for i in range(colors_len):
+ p1 = (round(input.size[0] / colors_len) * i, input.size[1])
+
+ output.paste(colors[i], [p1[0], p1[1], p2[0], p2[1]])
+ output.paste(input)
+
+ # output.save("output.png")
+ output.show()
+
+def main(file):
+ # NOTE: The arguments to this function were stolen from the library's internal code.
+ colorz_tuple = clz.colorz(file, 1, 170, 200, 50)[0][1]
+ normalized_tuple = (colorz_tuple[0] / 256, colorz_tuple[1] / 256, colorz_tuple[2] / 256)
+ input_color = Color(rgb=normalized_tuple)
+ colors = rotate(input_color)
+
+ terminal_colors = {"red": 0, "green": 120, "yellow": 60, "blue": 240, "magenta": 300, "cyan": 180}
+
+ for key in terminal_colors:
+ color, _= select_nearest(terminal_colors[key], colors)
+ terminal_colors[key] = color.hex
+
+ # Formulate a propper list of colors
+ palette = list(terminal_colors.values())
+ palette.insert(0, "#1a1a1a") # my favorite constant black
+ palette.append("#efefef") # my favorite constant white
+
+ return palette, input_color
+
+if __name__ == "__main__":
+ path = sys.argv[1]
+ file = open(path, "rb")
+
+ palette, dominant_color = main(file)
+
+ save_image(palette, path)
+ print(dominant_color)
+