diff --git a/color_manager/gui.py b/color_manager/gui.py index 80f05237..17d2fc7b 100644 --- a/color_manager/gui.py +++ b/color_manager/gui.py @@ -10,7 +10,7 @@ import os, ngtk, utils def recolor(src_path, dest_path, name, replacement, progress_bar, status): """Recursively copies and converts a source folder into a destination, given a either a color or a palette.""" - is_mono, new_colors = utils.get_input_colors(replacement) + new_colors, smooth, is_mono = utils.get_input_colors(replacement) dest_path = utils.copy_pack(src_path, dest_path, name) svg_paths = utils.get_paths(dest_path, [".svg"]) img_paths = utils.get_paths(dest_path, [".png", ".jpg", ".jpeg"]) @@ -40,7 +40,7 @@ def recolor(src_path, dest_path, name, replacement, progress_bar, status): img = Image.open(path) if is_mono: img = utils.monochrome_img(img, new_colors) - else: img = utils.multichrome_img(img, new_colors) + else: img = utils.multichrome_img(img, new_colors, smooth) img.save(path) diff --git a/color_manager/utils.py b/color_manager/utils.py index 8dfc6e2f..ab89b00a 100644 --- a/color_manager/utils.py +++ b/color_manager/utils.py @@ -99,18 +99,18 @@ def load_palette_file(path:str) -> Dict[str,LabColor]: palette = json.load(file) return palette -def get_input_colors(resource) -> List[str]: - """Returns an HSL tuple, or a list of colors, depending on the input, as well as a boolean indicating either.""" +def get_input_colors(resource) -> Tuple[List[str],bool,bool]: + """Returns an HSL tuple, or a list of colors, depending on the input, as well as a boolean indicating which one, as well as if the palettes specifies smoothing pngs/jpgs.""" if isinstance(resource, tuple) and len(resource) == 3: - return True, resource + return resource, False, True elif type(resource) is str: - colors = load_palette_file(resource)["colors"] - return False, generate_palette_dict(colors) + palette_file = load_palette_file(resource) + return generate_palette_dict(palette_file["colors"]), palette_file["smooth"], False else: - return False, generate_palette_dict(resource["colors"]) + return generate_palette_dict(resource["colors"]), palette_file["smooth"], False def get_svg_colors(svg:str) -> Set[str]: """Return a list of all unique colors within a given string @@ -300,11 +300,13 @@ def monochrome_img(img:Image, hsl:Tuple[float,float,float]) -> Image: return img -def multichrome_img(img:Image, new_colors:Dict[str,LabColor]) -> Image: +def multichrome_img(img:Image, new_colors:Dict[str,LabColor], smooth:bool) -> Image: """Replace colors in a given image with the closest match within a given color palette.""" - img = img.convert("P") + if smooth: img = img.convert("P", palette=Image.ADAPTIVE, colors=256) + else: img = img.convert("P") + palette = img.getpalette() rgb_palette = [(palette[i], palette[i+1], palette[i+2]) for i in range(0, len(palette), 3)] @@ -323,7 +325,7 @@ def multichrome_img(img:Image, new_colors:Dict[str,LabColor]) -> Image: def recolor(src_path:str, dest_path:str, name:str, replacement) -> None: """Recursively copies and converts a source folder into a destination, given a either a color or a palette.""" - is_mono, new_colors = get_input_colors(replacement) + new_colors, smooth, is_mono = get_input_colors(replacement) dest_path = copy_pack(src_path, dest_path, name) svg_paths = get_paths(dest_path, [".svg"]) img_paths = get_paths(dest_path, [".png", ".jpg", ".jpeg"]) @@ -344,6 +346,6 @@ def recolor(src_path:str, dest_path:str, name:str, replacement) -> None: img = Image.open(path) if is_mono: img = monochrome_img(img, new_colors) - else: img = multichrome_img(img, new_colors) + else: img = multichrome_img(img, new_colors, smooth) img.save(path) diff --git a/palettes/catppuccin.json b/palettes/catppuccin.json index adf34537..f718162f 100644 --- a/palettes/catppuccin.json +++ b/palettes/catppuccin.json @@ -1,6 +1,7 @@ { "name": "Catppuccin Latte", "desc": "Pastel theme that aims to be the middle ground between low and high contrast themes.", + "smooth": false, "colors": [ "dc8a78", "#dd7878", diff --git a/palettes/dracula.json b/palettes/dracula.json index b0b32678..f40ef99d 100644 --- a/palettes/dracula.json +++ b/palettes/dracula.json @@ -1,6 +1,7 @@ { "name": "Dracula", "desc": "Dark mode color scheme with vibrant and contrasting colors.", + "smooth": false, "colors": [ "#44475a", "#f8f8f2", diff --git a/palettes/nord.json b/palettes/nord.json index cbdc78bf..27b8b1cd 100644 --- a/palettes/nord.json +++ b/palettes/nord.json @@ -1,6 +1,7 @@ { "name": "Nord", "desc": "An arctic, north-bluish color palette.", + "smooth": true, "colors": [ "#434c5e", "#4c566a", diff --git a/palettes/one_dark.json b/palettes/one_dark.json index a0db3e5d..d59df951 100644 --- a/palettes/one_dark.json +++ b/palettes/one_dark.json @@ -1,6 +1,7 @@ { "name": "One Dark", "desc": "Dark grey background with vibrant colors.", + "smooth": true, "colors": [ "#282C34", "#E06C75", diff --git a/readme.md b/readme.md index 588d288f..262f771f 100644 --- a/readme.md +++ b/readme.md @@ -6,12 +6,13 @@ Color Manager is a program for recoloring and manipulating existing icon packs, ![gui](resources/gui.png) -**Instanty recolor artwork such as wallpapers.** +**Instantly recolor artwork such as wallpapers.** | Operation | Result | | :---------: | ------ | -| Original | ![1](resources/original.png) | -| Monochrome: (0.6, 0.54, 0.5) | ![2](resources/mono.png) | -| Multichrome: dracula.json | ![3](resources/multi.png) | +| **Original** | ![1](resources/original.png) | +| **Monochrome**:
(0.6, 0.54, 0.5) | ![2](resources/mono.png) | +| **Multichrome**:
`nord.json`
`smooth=false` | ![3](resources/multi_accurate.png) | +| **Multichrome**:
`nord.json`
`smooth=true` | ![3](resources/multi_smooth.png) | **GUI Demo**: ![demo](resources/demo.gif) @@ -45,6 +46,7 @@ Speeds were recorded with an Intel i7-4770K CPU. Any asset can serve as the base **Tip**: To increase the quality, i.e. decrease the perceived noise of multichromatic recolorings of pngs/jpgs, either... - Increase the number of colors in the palette you provide to the program, e.g. populate it with slight variations of the existing colors - Decrease the number of colors in your original image, e.g. using a function like `Image.quantize()` from `pillow`. +- Experiment with setting `smooth` to `true`/`false` in the palette json file. Both will be implemented as optional automatic adjustments in the future. diff --git a/resources/multi.png b/resources/multi.png deleted file mode 100644 index 3e74acc4..00000000 Binary files a/resources/multi.png and /dev/null differ diff --git a/resources/multi_accurate.png b/resources/multi_accurate.png new file mode 100644 index 00000000..677200bb Binary files /dev/null and b/resources/multi_accurate.png differ diff --git a/resources/multi_smooth.png b/resources/multi_smooth.png new file mode 100644 index 00000000..69ab0d95 Binary files /dev/null and b/resources/multi_smooth.png differ diff --git a/test.ipynb b/test.ipynb index d559252a..ce3515a5 100644 --- a/test.ipynb +++ b/test.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -12,9 +12,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Processing svgs: 0%| | 0/6 [00:00