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,

-**Instanty recolor artwork such as wallpapers.**
+**Instantly recolor artwork such as wallpapers.**
| Operation | Result |
| :---------: | ------ |
-| Original |  |
-| Monochrome: (0.6, 0.54, 0.5) |  |
-| Multichrome: dracula.json |  |
+| **Original** |  |
+| **Monochrome**:
(0.6, 0.54, 0.5) |  |
+| **Multichrome**:
`nord.json`
`smooth=false` |  |
+| **Multichrome**:
`nord.json`
`smooth=true` |  |
**GUI Demo**:

@@ -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, ?file/s]"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "Processing svgs: 100%|██████████| 6/6 [00:00<00:00, 84.43file/s]\n",
+ "Processing imgs: 100%|██████████| 2/2 [00:01<00:00, 1.27file/s]\n"
+ ]
+ }
+ ],
"source": [
"from color_manager import utils\n",
"\n",
@@ -22,9 +38,9 @@
"name = \"my_pack2\"\n",
"dest = \"~/Downloads\"\n",
"hsl = (0.6, 0.54, 0.5) # = rc.normalize_hsl(180, 50, 50)\n",
- "palette = \"palettes/dracula.json\"\n",
+ "palette = \"palettes/nord.json\"\n",
"\n",
- "utils.recolor(src, dest, name, hsl) # hsl or palette"
+ "utils.recolor(src, dest, name, palette) # hsl or palette"
]
}
],