Iconolatry
Converter (encode / decode) for .ICO files
Install / Use
/learn @SystemRage/IconolatryREADME
Iconolatry
Advanced Icon Converter
Why
There are several online converters, icon makers and favicon generators that can
transform image formats in .ico files or to achieve reverse process,
but only a few of them are really working and none of these provides an API.
So i developped a pure python small library, not using external software (like ImageMagick),
to perform the above operations.
Features
-
Gives detailed info about conversion process.
-
You can use it as bare module inside your projects or running it with CLI commands.
-
Reads
.icoand.curformats:- You can decode a single icon / cursor, a list of icon / cursor(s), a folder, a list of folders, or mixing...
- You can decode icon / cursor(s) as bytes stream(s) too.
- You can select output paths, output file names, output file formats (all those supported by PIL) for every conversion process.
- Supports decoding multi-size and / or multi-depth icons.
- Checks if the image AND mask is correct, otherwise is recomputed if needs.
-
Writes
.icoand.curusing a set of images (whose formats are supported by PIL):- You can convert a single image, a list of images, a folder, a list of folders, or mixing...
- You can select output paths, output file names, output file formats (
.ico,.cur) for every conversion process. - You can generate
.icomulti-format (packing many images with different sizes and depths). - You can provide fixed resize values or automatically let to resize input images to the nearest standard icon size.
- You can provide hotspots for
.curconversions. - You can provide custom palettes to apply during conversion (for indexed images).
Requirements
Python 3+PIL (Pillow)
Options
Encoder
| Parameter | CLI | Type | Description |
|-------------------|-----|-----------------|-----------------------------------------------------------------------------------------------------|
| paths_images | -i| list of lists | every list can contain one/more image(s) path(s) and/or one/more folder image(s) path(s) to convert |
| paths_icocur | -o| list | contains output path(s) for every resulting conversion. If isn't defined, working directory is used |
| names_icocur | -n| list | contains output name(s) for every resulting conversion. If paths_images contains a folder path and corresponding names_icocur is defined, a multi-.ico is created, otherwise every image in folder path is converted to a single .ico/.cur |
| formats_icocur | -f| list | contains format(s) for every resulting conversion ('.ico' or '.cur'). If .cur, can be specified hotspot x (integer) and hotspot y (integer) using a tuple; example: ('.cur', 2, 5) |
| type_resize | -r| string or tuple | with 'up256_prop' dimensions >256 pixels are resized keeping global image aspect ratio, with 'up256_no_prop' dimensions >256 pixels are resized without keeping global image aspect ratio, with 'square' dimensions are resized to nearest square standard size, with a tuple (width, height) for a custom resize |
| custom_palettes | -p| dict | the key is a tuple (mode, bitdepth), the value can be a list of RGB tuples [(R1,G1,B1),...,(Rn,Bn,Gn)] (usual palette format) or a flat list [V1,V2,...,Vn] (compact format for grayscale palette) or a .gpl file path |
Decoder
| Parameter | CLI | Type | Description |
|------------------|-----|------|---------------------------------------------------------------------------------------------------|
| paths_icocurs | -i| list | contains one/more icon/cursor(s) path(s) and/or one/more folder icon/cursor(s) path(s) to convert |
| paths_image | -o| list | contains output path(s) for every resulting conversion. If isn't defined, working directory is used |
| names_image | -n| list | contains output name(s) for every resulting conversion |
| formats_image | -f| list | contains format(s) for every resulting conversion (all saving PIL formats) |
| rebuild | -u| bool | if True, recompute mask from the alpha channel data |
Usage Examples
How to write an .ico.
>>> conv = Encode([['/path/input/test0.png']], paths_icocur = ['/path/output'], names_icocur = ['myname'], formats_icocur = ['.ico'],
type_resize = (48, 28))
>>> conv.all_icocur_written
{'/path/output/myname.ico': [{'file': '/path/input/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32', 'resize': '48 x 28'}]}
python3 Iconolatry.py encode -i /path/input/test0.png -o /path/output -n myname -f .ico -r "(48, 28)"
How to write a .cur.
>>> conv = Encode([['/path/input/test0.png']], paths_icocur = ['/path/output'], names_icocur = ['myname'], formats_icocur = [('.cur', 2, 5)],
custom_palettes = {('1', 1) : '/path/palettes/custom1bit.gpl')
>>> conv.all_icocur_written
{'/path/output/myname.cur': [{'file': '/path/input/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32'}]}
python3 Iconolatry.py encode -i /path/input/test0.png -o /path/output -n myname -f "('.cur', 2, 5)" -p "{('1', 1) : '/path/palettes/custom1bit.gpl'}"
How to write a multi-.ico.
>>> conv = Encode([['/path/input/test0.png', '/path/input/test1.bmp', '/path/input/test2.jpg']], paths_icocur = [''],
names_icocur = [''], formats_icocur = ['.ico'])
>>> conv.all_icocur_written
{'/path/working/directory/multi.ico': [{'file': '/path/input/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32'}, {'file': '/path/input/test1.bmp', 'mode': 'grayscale', 'depth': 4, 'size': '48 x 48'}, {'file': '/path/input/test2.jpg', 'mode': 'grayscale', 'depth': 8, 'size': '16 x 16'}]
}
Note how the multi name is auto-assigned because names_icocur isn't setted.
python3 Iconolatry.py encode -i /path/input/test0.png /path/input/test1.bmp /path/input/test2.jpg -f .ico
How to write more .icos and/or .curs together.
>>> conv = Encode([['/path/input/test0.png', '/path/input/test1.png'], ['/path/input/test2.png']],
paths_icocur = ['/path/outputA', '/path/outputB'],
names_icocur = ['test01', 'test2'],
formats_icocur = ['.ico', '.cur'])
>>> conv.all_icocur_written
{'/path/outputA/test01.ico': [{'file': '/path/input/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32'}, {'file': '/path/input/test1.png', 'mode': 'grayscale', 'depth': 4, 'size': '48 x 48'}],
'/path/outputB/test2.cur': [{'file': '/path/input/test2.png', 'mode': 'grayscale', 'depth': 8, 'size': '16 x 16'}]
}
python3 Iconolatry.py encode -i /path/input/test0.png /path/input/test1.png -o /path/outputA -i /path/input/test2.png -o /path/outputB
-n test01 test2 -f .ico .cur
How to encode image folders.
>>> conv = Encode([['/path/input/folder'], ['/path/input/folder']], paths_icocur = ['/path/outputA', '/path/outputB'],
names_icocur = ['mymultico', ''],
formats_icocur = ['.ico', '.cur'])
>>> conv.all_icocur_written
{'/path/outputA/mymulti.ico': [{'file': '/path/input/folder/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32'}, {'file': '/path/input/folder/test1.png', 'mode': 'grayscale', 'depth': 4, 'size': '48 x 48'}, {'file': '/path/input/folder/test2.png', 'mode': 'grayscale', 'depth': 8, 'size': '16 x 16'}],
'/path/outputB/test0.cur': [{'file': '/path/input/folder/test0.png', 'mode': 'grayscale', 'depth': 1, 'size': '32 x 32', 'hotspot_x': 0, 'hotspot_y': 0}],
'/path/outputB/test1.cur': [{'file': '/path/input/folder/test1.png', 'mode': 'grayscale', 'depth': 4, 'size': '48 x 48', 'hotspot_x': 0, 'hotspot_y': 0}],
'/path/outputB/test2.cur': [{'file': '/path/input/folder/test2.png', 'mode': 'grayscale', 'depth': 8, 'size': '16 x 16', 'hotspot_x': 0, 'hotspot_y': 0}]
}
python3 Iconolatry.py encode -i /path/input/folder -o /path/outputA -n mymultico -f .ico -i /path/input/folder -o /path/outputB -f .cur
How to read more .ico and/or .cur together.
>>> conv = Decode(['/path/input/cursor.cur', '/path/input/multicon.ico'], paths_image = [''], names_image = [''], formats_image = ['.png', '.bmp'])
>>> conv.all_icocur_readed
{'/path/input/cursor.cur': {'image_0': {'im_obj': <PIL.Image.Image image mode=RGBA size=32x32 at 0x7FDEF936C780>, 'depth': 32, 'hotspot_x': 0, 'hotspot_y': 0, 'saved': '/path/working/directory/cursor.png'}},
'/path/input/multicon.ico': {'image_0': {'im_obj': <PIL.Image.Image image mode=RGBA size=16x16 at 0x7FDEF936C860>, 'depth': 1, 'saved': '/path/working/directory/multicon_0.bmp'}, 'image_1': {'im_obj': <PIL.Image.Image image mode=RGBA size=32x32 at 0x7FDEF936C630>, 'depth': 24, 'saved': '/path/working/directory/multicon_1.bmp'}, 'image_2': {'im_obj': <PIL.Image.Image image mode=RGBA size=48x48 at 0x7FDEF936C4A8>, 'depth': 32, 'saved': '/path/working/directory/multicon_2.bmp'}}
}
python3 Iconolatry.py decode -i /path/input/cursor.cur /path/input/multicon.ico -f .png .bmp
How to decode image folders.
>>> conv = Decode(['/path/input/folder'], paths_image = ['/path/outputA'], names_image = ['customname'], rebuild = True)
>>> conv.all_icocur_readed
{'/path/input/folder/test0.cur': {'image_0': {'im_obj': <PIL.Image.Image image mode=RGBA size=16x16 at 0x7FDFDE8E52E8>, 'depth': 1, 'hotspot_x': 0, 'hotspot_y': 0, 'saved': '/path/outputA/customname_0.png'}},
'/path/input/folder/test1.cur': {'image_0': {'im_obj': <PIL.Image.Image image mode=RGBA size=48x48 at 0x7FDFDE8E5438>, 'depth': 32, 'hotspot_x': 0, 'hotspot_y': 0, 'saved': '/path/outputA/customname_1.png'}},
'/path/
