#!/usr/bin/env python3 """ Utility to build an .ico file from a list of PNGs of different sizes. Uses only Python's standard library so it can run in restricted environments. """ from __future__ import annotations import argparse import struct from pathlib import Path PNG_SIGNATURE = b"\x89PNG\r\n\x1a\n" def read_png_dimensions(data: bytes) -> tuple[int, int]: if not data.startswith(PNG_SIGNATURE): raise ValueError("All inputs must be PNG files.") width, height = struct.unpack(">II", data[16:24]) return width, height def build_icon(png_paths: list[Path], output: Path) -> None: png_data = [p.read_bytes() for p in png_paths] entries = [] offset = 6 + 16 * len(png_data) # icon header + entries for data in png_data: width, height = read_png_dimensions(data) entry = { "width": width if width < 256 else 0, "height": height if height < 256 else 0, "colors": 0, "reserved": 0, "planes": 1, "bit_count": 32, "size": len(data), "offset": offset, "data": data, } entries.append(entry) offset += entry["size"] header = struct.pack(" None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("output", type=Path) parser.add_argument("inputs", nargs="+", type=Path) args = parser.parse_args() if not args.inputs: raise SystemExit("Provide at least one PNG input.") build_icon(args.inputs, args.output) if __name__ == "__main__": main()