diff --git a/color_manager/utils.py b/color_manager/utils.py
index ab89b00a..4d5b5a30 100644
--- a/color_manager/utils.py
+++ b/color_manager/utils.py
@@ -6,7 +6,7 @@ from tqdm import tqdm
from colormath.color_objects import sRGBColor, LabColor
from colormath.color_conversions import convert_color
from colormath.color_diff import delta_e_cie2000
-from PIL import Image
+from PIL import Image, ImageDraw
import os, re, shutil, json
# Global constants -------------------------------------------------------------
@@ -349,3 +349,31 @@ def recolor(src_path:str, dest_path:str, name:str, replacement) -> None:
else: img = multichrome_img(img, new_colors, smooth)
img.save(path)
+
+def extract_colors(img_path, num_colors=8, save_path=None, pixels=50, cols=10):
+ img = Image.open(img_path)
+
+ colors = img.convert('P', palette=Image.ADAPTIVE, colors=num_colors)
+ colors = colors.getpalette()[0:num_colors*3]
+
+ colors = ['#{:02X}{:02X}{:02X}'.format(colors[i], colors[i+1], colors[i+2]) for i in range(0, len(colors), 3)]
+
+ if save_path != None:
+ n = len(colors)
+ if n < cols: cols = n
+
+ rows = -(-len(colors) // cols)
+ width = cols * pixels; height = rows * pixels
+
+ img = Image.new("RGBA", (width, height))
+ draw = ImageDraw.Draw(img)
+
+ for i, hex_color in enumerate(colors):
+ row = i // cols; col = i % cols
+ x0 = col * pixels; y0 = row * pixels
+ x1 = x0 + pixels; y1 = y0 + pixels
+ draw.rectangle([x0, y0, x1, y1], fill=hex_color)
+
+ img.save(save_path, format="png")
+
+ return colors
diff --git a/readme.md b/readme.md
index 2feed0c0..0726be24 100644
--- a/readme.md
+++ b/readme.md
@@ -13,6 +13,7 @@ Color Manager is a program for recoloring and manipulating existing icon packs,
| **Monochrome**:
`(0.6,0.54,0.5)` |  |
| **Multichrome**:
`nord.json`
`smooth=false` |  |
| **Multichrome**:
`nord.json`
`smooth=true` |  |
+| **Color Extraction**:
Original `num=10` |  |
**GUI Demo**:

@@ -37,11 +38,12 @@ Color Manager is a program for recoloring and manipulating existing icon packs,
## Features
-Currently, two types of recoloring operations are supported:
-| Type | Result | Speed | Supports |
-| ----------- | ------ | ---------------- | -------- |
-| Monochrome | A monochromatic variant, colored by appropriate shades of the provided base color. | ~5000 svgs/sec | svg, png, jpg |
-| Multichrome | A multichromatic variant, where all colors are replaced by their nearest perceived equivalent that adheres to the provided color palette. | ~100 svgs/sec | svg, png, jpg |
+Currently, three operations are supported:
+| Type | Result | Speed | Supports |
+| ---- | ------ | ----- | -------- |
+| Monochrome recoloring | A monochromatic variant, colored by appropriate shades of the provided base color. | ~5000 svgs/sec | svg, png, jpg |
+| Multichrome recoloring | A multichromatic variant, where all colors are replaced by their nearest perceived equivalent that adheres to the provided color palette. | ~100 svgs/sec | svg, png, jpg |
+| Extract colors | Returns and optionally saves the color palette of an image, in specified detail. | ~100 colors/sec | png, jpg |
Speeds were recorded with an Intel i7-4770K CPU. Any asset can serve as the base for any color palette or base color. Svg recolorings will always be perfect, but png/jpgs may require experimentation.
@@ -52,18 +54,27 @@ Speeds were recorded with an Intel i7-4770K CPU. Any asset can serve as the base
## Using the Program
-Either import `utils` into your own script and call the recoloring functions, e.g.:
+Either import `utils` into your own script and call its functions, e.g.:
```python
from color_manager import utils
```
+Recoloring:
```python
src = "test_pack"
name = "my_pack"
dest = "~/Downloads"
-hsl = (0.5, 0.5, 0.5) # = rc.norm_hsl(180, 50, 50)
+hsl = (0.5, 0.5, 0.5) # = rc.norm_hsl(180, 50, 50)
palette = "palettes/dracula.json"
-utils.recolor(src, dest, name, hsl) # hsl or palette.
+utils.recolor(src, dest, name, hsl) # Either hsl or palette.
+```
+Extracting:
+```python
+image = "test_pack/imgs/lake_cabin.png"
+num_colors = 10
+output = "resources/palette.png" # Optional - if given, saves colors as image.
+
+utils.extract_colors(image, num_colors, output)
```
Or launch the GUI by running `python3 color_manager/gui.py` in a terminal from the project's root directory. The GUI will adopt your active theme. Dependencies: `colormath`, `tqdm` and `pillow`. For the GUI, `pygobject` (GTK bindings) must also be installed.
diff --git a/resources/palette.png b/resources/palette.png
new file mode 100644
index 00000000..392627a4
Binary files /dev/null and b/resources/palette.png differ
diff --git a/test.ipynb b/test.ipynb
index ce3515a5..7e9db80f 100644
--- a/test.ipynb
+++ b/test.ipynb
@@ -35,13 +35,48 @@
"from color_manager import utils\n",
"\n",
"src = \"test_pack\"\n",
- "name = \"my_pack2\"\n",
+ "name = \"my_pack\"\n",
"dest = \"~/Downloads\"\n",
"hsl = (0.6, 0.54, 0.5) # = rc.normalize_hsl(180, 50, 50)\n",
"palette = \"palettes/nord.json\"\n",
"\n",
"utils.recolor(src, dest, name, palette) # hsl or palette"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['#C0829C',\n",
+ " '#596996',\n",
+ " '#345D89',\n",
+ " '#284F81',\n",
+ " '#074C71',\n",
+ " '#213B6D',\n",
+ " '#0B385A',\n",
+ " '#053655',\n",
+ " '#013854',\n",
+ " '#012941']"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from color_manager import utils\n",
+ "\n",
+ "image = \"test_pack/imgs/lake_cabin.png\"\n",
+ "num_colors = 10\n",
+ "output = \"./palette.png\" # if given, saves colors as image.\n",
+ "\n",
+ "utils.extract_colors(image, num_colors, output)"
+ ]
}
],
"metadata": {