<p>I'm looking to create <code>favicon.ico</code> files programatically from Python, but PIL only has support for reading <code>ico</code> files.</p>

[{'answer_id': 45519, 'author': 'codeape', 'author_id': 3571, 'author_profile': 'https://Stackoverflow.com/users/3571', 'pm_score': 3, 'selected': False, 'text': '<p>Perhaps the following would work:</p>\n\n<ul>\n<li>Generate your icon image using PIL</li>\n<li>Convert the image to .ico format using the python interface to ImageMagick, <a href="http://www.imagemagick.org/download/python/" rel="noreferrer">PythonMagick</a></li>\n</ul>\n\n<p>I have not tried this approach. The ImageMagick convert command line program was able to convert a .png file to .ico format, so at least ImageMagick supports the .ico format.</p>\n'}, {'answer_id': 45520, 'author': 'thing2k', 'author_id': 3180, 'author_profile': 'https://Stackoverflow.com/users/3180', 'pm_score': 1, 'selected': False, 'text': "<p>I don't know if this applies for all cases, but on WinXP an .ico can be a bmp of size 16x16, 32x32 or 64x64. Just change the extension to ico from bmp and you're ready to go.</p>\n"}, {'answer_id': 45832, 'author': 'Douglas Leeder', 'author_id': 3978, 'author_profile': 'https://Stackoverflow.com/users/3978', 'pm_score': 4, 'selected': True, 'text': '<p>According to <a href="http://en.wikipedia.org/wiki/Favicon" rel="noreferrer">Wikipedia</a> modern browsers can handle favicons in PNG format, so maybe you could just generate that?</p>\n\n<p>Alternatively the <a href="http://en.wikipedia.org/wiki/ICO_(icon_image_file_format)" rel="noreferrer">ICO article</a> describes the format...</p>\n'}, {'answer_id': 36168447, 'author': 'Ronan Paixão', 'author_id': 3754432, 'author_profile': 'https://Stackoverflow.com/users/3754432', 'pm_score': 6, 'selected': False, 'text': '<p>You can use <a href="http://pillow.readthedocs.org" rel="noreferrer">Pillow</a>:</p>\n\n<pre><code>from PIL import Image\nfilename = r\'logo.png\'\nimg = Image.open(filename)\nimg.save(\'logo.ico\')\n</code></pre>\n\n<p>Optionally, you may specify the icon sizes you want:</p>\n\n<pre><code>icon_sizes = [(16,16), (32, 32), (48, 48), (64,64)]\nimg.save(\'logo.ico\', sizes=icon_sizes)\n</code></pre>\n\n<p>The <a href="http://pillow.readthedocs.org/en/3.1.x/handbook/image-file-formats.html" rel="noreferrer">Pillow docs</a> say that by default it will generate sizes \n<code>[(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (255, 255)]</code> and any size bigger than the original size or 255 will be ignored.</p>\n\n<p>Yes, it is in the <strong>Read-only</strong> section of the docs, but it works to some extent.</p>\n'}, {'answer_id': 52333963, 'author': 'Overdrivr', 'author_id': 4218017, 'author_profile': 'https://Stackoverflow.com/users/4218017', 'pm_score': 2, 'selected': False, 'text': '<p>If you have <a href="https://imageio.readthedocs.io/en/stable/format_ico-pil.html#ico-pil" rel="nofollow noreferrer">imageio</a>, (probably the best library for reading/writing images in Python), you can use it:</p>\n\n<pre><code>import imageio\n\nimg = imageio.imread(\'logo.png\')\nimageio.imwrite(\'logo.ico\', img)\n</code></pre>\n\n<p>Install is as easy as </p>\n\n<pre><code>pip install imageio\n</code></pre>\n'}, {'answer_id': 58770704, 'author': 'Jan', 'author_id': 6590884, 'author_profile': 'https://Stackoverflow.com/users/6590884', 'pm_score': 3, 'selected': False, 'text': '<p>Although this question is rather old, it\'s a prominent search result for using Python to convert PNG files to ICO, so I thought I\'ll add my two cents.</p>\n\n<p>If all you want is a favicon, Douglas Leeder\'s answer seems perfectly fine to me. If you have one high-resolution PNG file of your logo and want to convert it to an ICO file, the answer of Ronan Paixão is probably the easiest way to go.</p>\n\n<p>But an ICO file can contain multiple images, intended for different resolutions, and I often found myself in the situation of wanting to have fine-grained control over these different resolutions, to avoid unfortunate anti-aliasing effects, which means that I want to provide each image resolution individually. Which means that I want to convert not a single, but multiple PNG files into a single ICO file. As far as I can see, the Pillow package doesn\'t provide this capability. Fortunately, a modern ICO file can contain multiple PNG files inside, so the task boils down to the simple challenge of writing some header entries. Depending on the situation, I wrote two functions, the first one basically the solution of Ronan Paixão, while the second one provides the functionality to join several PNG files into one ICO file:</p>\n\n<pre><code>from pathlib import Path\nfrom PIL import Image\n\n\ndef bake_one_big_png_to_ico(sourcefile, targetfile, sizes=None):\n    """Converts one big PNG into one ICO file.\n\n    args:\n        sourcefile (str): Pathname of a PNG file.\n        targetfile (str): Pathname of the resulting ICO file.\n        sizes (list of int): Requested sizes of the resulting\n            icon file, defaults to [16, 32, 48].\n\n    Use this function if you have one big, square PNG file\n    and don’t care about fine-tuning individual icon sizes.\n\n    Example::\n\n        sourcefile = "Path/to/high_resolution_logo_512x512.png"\n        targetfile = "Path/to/logo.ico"\n        sizes = [16, 24, 32, 48, 256]\n        bake_one_big_png_to_ico(sourcefile, targetfile, sizes)\n    """\n    if sizes is None:\n        sizes = [16, 32, 48]\n    icon_sizes = [(x, x) for x in sizes]\n    Image.open(sourcefile).save(targetfile, icon_sizes=icon_sizes)\n\n\ndef bake_several_pngs_to_ico(sourcefiles, targetfile):\n    """Converts several PNG files into one ICO file.\n\n    args:\n        sourcefiles (list of str): A list of pathnames of PNG files.\n        targetfile (str): Pathname of the resulting ICO file.\n\n    Use this function if you want to have fine-grained control over\n    the resulting icon file, providing each possible icon resolution\n    individually.\n\n    Example::\n\n        sourcefiles = [\n            "Path/to/logo_16x16.png",\n            "Path/to/logo_32x32.png",\n            "Path/to/logo_48x48.png"\n        ]\n        targetfile = "Path/to/logo.ico"\n        bake_several_pngs_to_ico(sourcefiles, targetfile)\n    """\n\n    # Write the global header\n    number_of_sources = len(sourcefiles)\n    data = bytes((0, 0, 1, 0, number_of_sources, 0))\n    offset = 6 + number_of_sources * 16\n\n    # Write the header entries for each individual image\n    for sourcefile in sourcefiles:\n        img = Image.open(sourcefile)\n        data += bytes((img.width, img.height, 0, 0, 1, 0, 32, 0, ))\n        bytesize = Path(sourcefile).stat().st_size\n        data += bytesize.to_bytes(4, byteorder="little")\n        data += offset.to_bytes(4, byteorder="little")\n        offset += bytesize\n\n    # Write the individual image data\n    for sourcefile in sourcefiles:\n        data += Path(sourcefile).read_bytes()\n\n    # Save the icon file\n    Path(targetfile).write_bytes(data)\n</code></pre>\n\n<p>The code presupposes that your PNG files are 32-Bit-per-Pixel RGBA images. Otherwise, the number 32 in the above code would have to be changed and should be replaced with some Pillow-image-sniffing.</p>\n'}, {'answer_id': 62374154, 'author': 'Mike R', 'author_id': 1621381, 'author_profile': 'https://Stackoverflow.com/users/1621381', 'pm_score': 1, 'selected': False, 'text': '<p>I was trying to batch convert my logo into multiple sizes for my python based app packaged with <a href="https://github.com/mherrmann/fbs-tutorial" rel="nofollow noreferrer">fbs</a> and ended up using the below to do this based on the above answers.</p>\n\n<p>worked perfectly even the .ico one generated and shows in Windows. In Linux it shows the one Icon.ico as compressed, but not too worried about that as its only going to be used in Windows.</p>\n\n<p><a href="https://i.stack.imgur.com/xE6x1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xE6x1.png" alt="enter image description here"></a></p>\n\n<pre><code>from PIL import Image\nicon_sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (255, 255)]\nimage = Image.open(\'/some/path/to/logo-python/logo.png\')\nfileoutpath = \'/some/path/to/logo-python/\'\nfor size in icon_sizes:\n    print(size[0])\n    fileoutname = fileoutpath + str(size[0]) + ".png"\n    new_image = image.resize(size)\n    new_image.save(fileoutname)\n\nnew_logo_ico_filename = fileoutpath + "Icon.ico"\nnew_logo_ico = image.resize((128, 128))\nnew_logo_ico.save(new_logo_ico_filename, format="ICO",quality=90)\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/45507', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/4203/']