Created
April 10, 2024 18:10
-
-
Save vslavik/6ca955b60d09a92bd39a28b2187fb0f9 to your computer and use it in GitHub Desktop.
Script to create ICO files from PNGs while preserving compresison
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# | |
# Create an .ico file from a bunch of PNGs. | |
# Unlike ImageMagick's convert, this does not convert PNGs into bitmaps or | |
# otherwise modify the source PNGs; in particular, their compression is | |
# preserved. | |
# | |
# ICO format is actually very simple: | |
# https://en.wikipedia.org/wiki/ICO_(file_format) | |
# | |
# Embedded PNGs as the only content are supported since Windows Vista. | |
# | |
import argparse | |
import struct | |
import io | |
import PIL.Image | |
ap = argparse.ArgumentParser() | |
ap.add_argument('inputs', nargs='+') | |
ap.add_argument('-o', '--output', required=True) | |
args = ap.parse_args() | |
png_data = [] | |
for path in args.inputs: | |
with open(path, 'rb') as fp: | |
png_data.append(fp.read()) | |
icons = [] | |
for data in png_data: | |
with PIL.Image.open(io.BytesIO(data)) as im: | |
w, h = im.size | |
icons.append((w, h, data)) | |
icons.sort() | |
with open(args.output, 'wb') as f: | |
f.truncate() | |
f.write(struct.pack('<HHH', 0, 1, len(icons))) | |
offset = 6 + 16 * len(png_data) | |
for w, h, data in icons: | |
if w > 255: | |
w = 0 | |
if h > 255: | |
h = 0 | |
f.write(struct.pack('<BBBBHHII', w, h, 0, 0, 1, 0, len(data), offset)) | |
offset += len(data) | |
for _, _, data in icons: | |
f.write(data) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Inspecting what the ICO file contains:
Extracting all sub-images from ICO file: