diff --git a/README.md b/README.md
index dac03353..9d0c7de5 100644
--- a/README.md
+++ b/README.md
@@ -49,6 +49,7 @@ We provided svg, ai, and fig template to make it easier. The specifications incl
- Name of the icon must be written in snake case.
- Because of we should not replace existing icon, new icon must be numbered that starts with 1.
- First icon must be not numbered.
+- If an icon variant for an existing icon is created it's maximum size in pixel - seperated with a dash, after potential numbering - is appended. The size must be followed by the unit shorthand 'px'.
```
Folder11
@@ -56,6 +57,7 @@ Folder11
├──📄 my_folder.svg
├──📄 my_folder-1.svg
└──📄 my_folder-2.svg
+ └──📄 my_folder-2-32px.svg
```
### Commit Naming
diff --git a/batch_convert_to_ico.py b/batch_convert_to_ico.py
new file mode 100644
index 00000000..5b0df76d
--- /dev/null
+++ b/batch_convert_to_ico.py
@@ -0,0 +1,114 @@
+import os
+from typing import Tuple, List, Dict
+import subprocess
+from pathlib import Path
+
+def convert_svg_to_ico(input_folder:str, output_folder:str, sizes:Tuple[int, ...]=(16,32,48,64,256)):
+ """
+ Converts a folder of .svg icons to a folder of .ico icons of various sizes.
+ Icons can be swapped based on a maximum size attributed to .svg icons, if their name ends with '-{size}px.svg'.
+ This function requires Imagemagick to be installed.
+
+ Args:
+ input_folder (str): The path to the folder containing the .svg icons.
+ output_folder (str): The path to the folder where the .ico icons will be saved.
+ sizes (Tuple[int, ...], optional): The sizes of the .ico icons. Defaults to (16, 32, 48, 64, 256).
+ """
+
+ def ends_with_px(string:str) -> bool:
+ if not string.endswith('px'): return False
+ parts:Tuple[str, ...] = string.rsplit('-', 1)
+ if len(parts) != 2: return False
+ return parts[1][:-2].isdigit()
+
+ def delete_folder(folder_path):
+ folder = Path(folder_path)
+ if folder.exists() and folder.is_dir():
+ for item in folder.iterdir():
+ if item.is_file():
+ item.unlink()
+ folder.rmdir()
+
+ sizes = sorted(sizes)
+
+ base_filenames:List[str] = [filename for filename in os.listdir(input_folder) if filename.lower().endswith('.svg')
+ and not any([ends_with_px(filename[:-4].lower()) for s in sizes])]
+ alt_filenames:List[str] = [filename for filename in os.listdir(input_folder) if filename.lower().endswith('.svg')
+ and any([ends_with_px(filename[:-4].lower()) for s in sizes[:-1]])]
+
+ # Iterate through all base .svg files in the input folder
+ for base_filename in base_filenames:
+ # print(base_filename)
+ inputs:List[Dict[str, int | str]] = []
+
+ for size in sizes:
+ assumed_filename:str = base_filename[:-4] + f'-{size}px.svg'
+ if assumed_filename not in alt_filenames: continue
+
+ alt_input_path:str = os.path.join(input_folder, assumed_filename)
+
+ inputs.append({'path': alt_input_path, 'maximum_size': size})
+
+ # Add version that comes for sizes above alt max sizes
+ inputs.append({'path': os.path.join(input_folder, base_filename), 'maximum_size': sizes[-1]})
+
+ # Step 1: Convert input.svg's to throughput.png's using Imagemagick
+ Path("temp_pngs").mkdir(parents=True, exist_ok=True)
+ throughput_paths:List[str] = [os.path.join("temp_pngs", f'{base_filename[:-4]}-{size_index}.png') for size_index in range(len(sizes))]
+ size_index:int = 0
+ # print(inputs)
+ input:Dict[str, int | str] = inputs.pop(0)
+ for size_index in range(len(sizes)):
+ # Go to next input if the current needed size is greater than input's maximum
+ if sizes[size_index] > input['maximum_size']:
+ input:Dict[str, int | str] = inputs.pop(0)
+ # print(input)
+ current_size:int = sizes[size_index]
+ throughput_path:str = throughput_paths[size_index]
+ try:
+ # magick convert -background transparent -resize x