From b2c8ce0b2e7a2ea7ed4a699b435801886e31592e Mon Sep 17 00:00:00 2001 From: midn8hustlr <4visekh@gmail.com> Date: Tue, 26 Mar 2024 12:54:21 +0530 Subject: [PATCH 1/3] Wave goodbye to material-color-utilities-python --- .../ags/scripts/color_generation/colorgen.sh | 2 +- .../generate_colors_material.py | 74 ++++++++----------- scriptdata/dependencies.conf | 2 +- 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/.config/ags/scripts/color_generation/colorgen.sh b/.config/ags/scripts/color_generation/colorgen.sh index 06551f018..ef0c0948c 100755 --- a/.config/ags/scripts/color_generation/colorgen.sh +++ b/.config/ags/scripts/color_generation/colorgen.sh @@ -46,7 +46,7 @@ elif [ "$backend" = "material" ]; then smartflag='--smart True' fi color_generation/generate_colors_material.py --path "$1" \ - --mode "$lightdark" --scheme "$materialscheme" --transparency "$transparency" --cache '.cache/ags/user/color.txt' $smartflag \ + --mode "$lightdark" --scheme "$materialscheme" --transparency "$transparency" --cache "$HOME/.cache/ags/user/color.txt" $smartflag \ > "$HOME"/.cache/ags/user/generated/material_colors.scss if [ "$2" = "--apply" ]; then cp "$HOME"/.cache/ags/user/generated/material_colors.scss "$HOME/.config/ags/scss/_material.scss" diff --git a/.config/ags/scripts/color_generation/generate_colors_material.py b/.config/ags/scripts/color_generation/generate_colors_material.py index 550a7a994..f9bff221f 100755 --- a/.config/ags/scripts/color_generation/generate_colors_material.py +++ b/.config/ags/scripts/color_generation/generate_colors_material.py @@ -1,60 +1,42 @@ #!/usr/bin/env python3 -from material_color_utilities_python import * -from pathlib import Path -import sys -import subprocess import argparse -import os - +from PIL import Image +from materialyoucolor.quantize import QuantizeCelebi +from materialyoucolor.score.score import Score from materialyoucolor.hct import Hct from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors +from materialyoucolor.utils.color_utils import rgba_from_argb, argb_from_rgb + +argb_to_hex = lambda argb: "#{:02X}{:02X}{:02X}".format(*map(round, rgba_from_argb(argb))) +hex_to_argb = lambda hex_code: argb_from_rgb(int(hex_code[1:3], 16), int(hex_code[3:5], 16), int(hex_code[5:], 16)) parser = argparse.ArgumentParser(description='Color generation script') parser.add_argument('--path', type=str, default=None, help='generate colorscheme from image') +parser.add_argument('--quality', type=int , default=1 , help='pixels to skip in image, setting 1 means skip no pixels') parser.add_argument('--color', type=str, default=None, help='generate colorscheme from color') parser.add_argument('--mode', type=str, choices=['dark', 'light'], default='dark', help='dark or light mode') parser.add_argument('--scheme', type=str, default=None, help='material scheme to use') parser.add_argument('--smart', type=str, default=False, help='decide scheme type based on image color') parser.add_argument('--transparency', type=str, choices=['opaque', 'transparent'], default='opaque', help='enable transparency') -parser.add_argument('--cache', type=str, default=None, help='file path (relative to home) to store the generated color') +parser.add_argument('--cache', type=str, default=None, help='file path to store the generated color') parser.add_argument('--debug', action='store_true', default=False, help='debug mode') args = parser.parse_args() -def hex_to_argb(hex_color): - color = hex_color.lstrip('#') - if len(color) != 6: - raise ValueError("Invalid color code!") - r = int(color[:2], 16) - g = int(color[2:4], 16) - b = int(color[4:], 16) - a = 255 - argb = (a << 24) | (r << 16) | (g << 8) | b - return argb - -def argb_to_hex(argb_value): - r = (argb_value >> 16) & 0xff - g = (argb_value >> 8) & 0xff - b = argb_value & 0xff - hex_r = format(r, '02x') - hex_g = format(g, '02x') - hex_b = format(b, '02x') - hex_color = f"#{hex_r}{hex_g}{hex_b}" - return hex_color - darkmode = (args.mode == 'dark') transparent = (args.transparency == 'transparent') print(f"$darkmode: {darkmode};") print(f"$transparent: {transparent};") if args.path is not None: - img = Image.open(args.path) - basewidth = 64 - wpercent = (basewidth/float(img.size[0])) - hsize = int((float(img.size[1])*float(wpercent))) - img = img.resize((basewidth,hsize),Image.Resampling.BICUBIC) - argb = sourceColorFromImage(img) + image = Image.open(args.path) + pixel_len = image.width * image.height + image_data = image.getdata() + pixel_array = [image_data[_] for _ in range(0, pixel_len, args.quality)] + colors = QuantizeCelebi(pixel_array, 128) + argb = Score.score(colors)[0] + if args.cache is not None: - export_color_file=os.environ['HOME'] + "/" + args.cache + export_color_file=args.cache with open(export_color_file, 'w') as file: file.write(argb_to_hex(argb)) hct = Hct.from_int(argb) @@ -95,21 +77,25 @@ def argb_to_hex(argb_value): if hasattr(color_name, "get_hct"): rgba = color_name.get_hct(scheme).to_rgba() r, g, b, a = rgba - hex_color = f"#{r:02X}{g:02X}{b:02X}" - print('$' + color + ': ' + hex_color + ';') + hex_code = f"#{r:02X}{g:02X}{b:02X}" + print('$' + color + ': ' + hex_code + ';') if args.debug == True: print('---------------------') - print('Hue', hct.hue) - print('Chroma', hct.chroma) - print('Tone', hct.tone) - print('Dark mode?', darkmode) - print('Scheme', args.scheme) + print('Hue:', hct.hue) + print('Chroma:', hct.chroma) + print('Tone:', hct.tone) + print(argb) + r, g, b, a = rgba_from_argb(argb) + hex_code = argb_to_hex(argb) + print('Selected Color:', "\x1B[38;2;{};{};{}m{}\x1B[0m".format(r, g, b, "\x1b[7m \x1b[7m"), hex_code) + print('Dark mode:', darkmode) + print('Scheme:', args.scheme) print('---------------------') for color in vars(MaterialDynamicColors).keys(): color_name = getattr(MaterialDynamicColors, color) if hasattr(color_name, "get_hct"): rgba = color_name.get_hct(scheme).to_rgba() r, g, b, a = rgba - hex_color = f"#{r:02X}{g:02X}{b:02X}" - print(color.ljust(32), "\x1B[38;2;{};{};{}m{}\x1B[0m".format(rgba[0], rgba[1], rgba[2], "\x1b[7m \x1b[7m"), hex_color) + hex_code = f"#{r:02X}{g:02X}{b:02X}" + print(color.ljust(32), "\x1B[38;2;{};{};{}m{}\x1B[0m".format(rgba[0], rgba[1], rgba[2], "\x1b[7m \x1b[7m"), hex_code) diff --git a/scriptdata/dependencies.conf b/scriptdata/dependencies.conf index 9bf850cad..ec88f714f 100644 --- a/scriptdata/dependencies.conf +++ b/scriptdata/dependencies.conf @@ -9,7 +9,7 @@ tinyxml2 gtkmm3 gtksourceviewmm cairomm ### Python # Add `python-setuptools-scm` and `python-wheel` explicitly to fix #197 -python-build python-material-color-utilities python-materialyoucolor-git python-pillow python-poetry python-pywal python-setuptools-scm python-wheel +python-build python-materialyoucolor-git python-pillow python-pywal python-setuptools-scm python-wheel ### Basic graphic env hyprland-git xorg-xrandr From a01f0af54062e529d9877cb17892667daf8e3b32 Mon Sep 17 00:00:00 2001 From: midn8hustlr <4visekh@gmail.com> Date: Tue, 26 Mar 2024 15:10:32 +0530 Subject: [PATCH 2/3] Resize image before for faster color generation --- .../color_generation/generate_colors_material.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.config/ags/scripts/color_generation/generate_colors_material.py b/.config/ags/scripts/color_generation/generate_colors_material.py index f9bff221f..f48fdde55 100755 --- a/.config/ags/scripts/color_generation/generate_colors_material.py +++ b/.config/ags/scripts/color_generation/generate_colors_material.py @@ -12,7 +12,7 @@ parser = argparse.ArgumentParser(description='Color generation script') parser.add_argument('--path', type=str, default=None, help='generate colorscheme from image') -parser.add_argument('--quality', type=int , default=1 , help='pixels to skip in image, setting 1 means skip no pixels') +parser.add_argument('--basewidth', type=int , default=128 , help='resize the image to the specified width for faster color generation') parser.add_argument('--color', type=str, default=None, help='generate colorscheme from color') parser.add_argument('--mode', type=str, choices=['dark', 'light'], default='dark', help='dark or light mode') parser.add_argument('--scheme', type=str, default=None, help='material scheme to use') @@ -29,15 +29,14 @@ if args.path is not None: image = Image.open(args.path) - pixel_len = image.width * image.height - image_data = image.getdata() - pixel_array = [image_data[_] for _ in range(0, pixel_len, args.quality)] - colors = QuantizeCelebi(pixel_array, 128) + wpercent = (args.basewidth/float(image.size[0])) + hsize = int((float(image.size[1])*float(wpercent))) + image = image.resize((args.basewidth, hsize), Image.Resampling.BICUBIC) + colors = QuantizeCelebi(image.getdata(), 128) argb = Score.score(colors)[0] if args.cache is not None: - export_color_file=args.cache - with open(export_color_file, 'w') as file: + with open(args.cache, 'w') as file: file.write(argb_to_hex(argb)) hct = Hct.from_int(argb) if(args.smart): @@ -85,7 +84,6 @@ print('Hue:', hct.hue) print('Chroma:', hct.chroma) print('Tone:', hct.tone) - print(argb) r, g, b, a = rgba_from_argb(argb) hex_code = argb_to_hex(argb) print('Selected Color:', "\x1B[38;2;{};{};{}m{}\x1B[0m".format(r, g, b, "\x1b[7m \x1b[7m"), hex_code) From 8c828fb27cb463448fc14b4da9de88ccd7145e4c Mon Sep 17 00:00:00 2001 From: midn8hustlr <4visekh@gmail.com> Date: Wed, 27 Mar 2024 21:59:34 +0530 Subject: [PATCH 3/3] Optimize the image resizing algo --- .../generate_colors_material.py | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/.config/ags/scripts/color_generation/generate_colors_material.py b/.config/ags/scripts/color_generation/generate_colors_material.py index f48fdde55..578347b55 100755 --- a/.config/ags/scripts/color_generation/generate_colors_material.py +++ b/.config/ags/scripts/color_generation/generate_colors_material.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 import argparse +import math from PIL import Image from materialyoucolor.quantize import QuantizeCelebi from materialyoucolor.score.score import Score @@ -12,7 +13,7 @@ parser = argparse.ArgumentParser(description='Color generation script') parser.add_argument('--path', type=str, default=None, help='generate colorscheme from image') -parser.add_argument('--basewidth', type=int , default=128 , help='resize the image to the specified width for faster color generation') +parser.add_argument('--size', type=int , default=128 , help='bitmap image size') parser.add_argument('--color', type=str, default=None, help='generate colorscheme from color') parser.add_argument('--mode', type=str, choices=['dark', 'light'], default='dark', help='dark or light mode') parser.add_argument('--scheme', type=str, default=None, help='material scheme to use') @@ -27,11 +28,24 @@ print(f"$darkmode: {darkmode};") print(f"$transparent: {transparent};") +def calculate_optimal_size (width, height, bitmap_size): + image_area = width * height; + bitmap_area = bitmap_size ** 2 + scale = math.sqrt(bitmap_area/image_area) if image_area > bitmap_area else 1 + new_width = round(width * scale) + new_height = round(height * scale) + if new_width == 0: + new_width = 1 + if new_height == 0: + new_height = 1 + return new_width, new_height + if args.path is not None: image = Image.open(args.path) - wpercent = (args.basewidth/float(image.size[0])) - hsize = int((float(image.size[1])*float(wpercent))) - image = image.resize((args.basewidth, hsize), Image.Resampling.BICUBIC) + wsize, hsize = image.size + wsize_new, hsize_new = calculate_optimal_size(wsize, hsize, args.size) + if wsize_new < wsize or hsize_new < hsize: + image = image.resize((wsize_new, hsize_new), Image.Resampling.BICUBIC) colors = QuantizeCelebi(image.getdata(), 128) argb = Score.score(colors)[0] @@ -81,6 +95,9 @@ if args.debug == True: print('---------------------') + if args.path is not None: + print('Image size: {} x {}'.format(wsize, hsize)) + print('Resized image: {} x {}'.format(wsize_new, hsize_new)) print('Hue:', hct.hue) print('Chroma:', hct.chroma) print('Tone:', hct.tone)