-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Open
Labels
Description
It seems there is no support for multiple icons in one icon file
import os
from optparse import OptionParser
from PIL import Image
def main():
parser = OptionParser(usage="usage: %prog [options] INPUTFILE")
parser.add_option("-f", "--format", dest="output_format", default="ico",
help="Output image format (default: ico)")
parser.add_option("-o", "--output", dest="output_file", help="Output file path (optional)")
parser.add_option("--debug", action="store_true", dest="debug", default=False,
help="Extract and save all icons from the generated .ico file for debugging.")
(options, args) = parser.parse_args()
if not args:
parser.print_help()
parser.error("Input file is required as the last argument.")
input_file = args[-1]
output_format = options.output_format.lower()
output_file = options.output_file
if not os.path.isfile(input_file):
parser.error(f"Input file '{input_file}' does not exist.")
if not output_file:
base, _ = os.path.splitext(input_file)
output_file = f"{base}.{output_format}"
base, _ = os.path.splitext(output_file)
if os.path.isfile(output_file):
answer = input(f"Output file '{output_file}' already exists. Overwrite? [y/n]: ").strip().lower()
if answer != "y" and answer != "yes":
print("Aborted by user.")
return
try:
with Image.open(input_file) as img:
if output_format == "ico":
sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
img = img.convert("RGBA")
# Create resized images for each size
resized_imgs = [img.resize(size, Image.LANCZOS) for size in sizes]
# Save a multi-icon .ico file containing all sizes
multi_icon_path = f"{base}.ico"
resized_imgs[0].save(multi_icon_path, format="ICO", sizes=sizes)
print(f"Saved multi-size icon: {multi_icon_path}")
# Save individual ICO files for each size
for i, size in enumerate(sizes):
out_path = f"{base}_{size[0]}x{size[1]}.ico"
resized_imgs[i].save(out_path, format="ICO", sizes=[size])
print(f"Saved {out_path}")
# Debug: extract all icons from the generated .ico file
if options.debug:
with Image.open(multi_icon_path) as ico_img:
try:
i = 0
extracted = set()
while True:
try:
ico_img.seek(i)
size = ico_img.size
out_path = f"{base}_extracted_{size[0]}x{size[1]}_{i}.png"
ico_img.save(out_path, format="PNG")
print(f"Extracted {out_path}")
extracted.add(size)
i += 1
except EOFError:
break
if len(extracted) == 1:
print("Warning: Only one icon size was extracted from the .ico file. "
"This may indicate a limitation in Pillow or the input image. "
"Try updating Pillow or using a square input image of at least 256x256.")
except Exception as e:
print(f"Error extracting icons: {e}")
else:
img.save(output_file, format=output_format.upper())
print(f"Converted '{input_file}' to '{output_file}' as format '{output_format}'.")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
main()Warning: Only one icon size was extracted from the .ico file. This may indicate a limitation in Pillow or the input image. Try updating Pillow or using a square input image of at least 256x256.