是否有用于生成.ico文件的Python库?

时间:2008-09-05 10:26:47

标签: python favicon

我希望以编程方式从Python创建favicon.ico文件,但PIP仅支持读取ico个文件。

6 个答案:

答案 0 :(得分:18)

您可以使用Pillow

from PIL import Image
filename = r'logo.png'
img = Image.open(filename)
img.save('logo.ico')

您可以选择指定所需的图标大小:

icon_sizes = [(16,16), (32, 32), (48, 48), (64,64)]
img.save('logo.ico', sizes=icon_sizes)

Pillow docs表示默认情况下会生成尺寸 [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (255, 255)],任何大于原始大小或255的大小都将被忽略。

是的,它位于文档的只读部分,但它在某种程度上有效。

答案 1 :(得分:8)

根据Wikipedia现代浏览器可以处理PNG格式的favicon,所以也许你可以生成它?

或者,ICO article描述格式......

答案 2 :(得分:7)

也许以下方法可行:

  • 使用PIL
  • 生成图标图像
  • 使用python界面将图像转换为.ico格式到ImageMagick,PythonMagick

我没有尝试过这种方法。 ImageMagick转换命令行程序能够将.png文件转换为.ico格式,因此至少ImageMagick支持.ico格式。

答案 3 :(得分:2)

我不知道这是否适用于所有情况,但在WinXP上,.ico可以是大小为16x16,32x32或64x64的bmp。只需将扩展名从bmp更改为ico就可以了。

答案 4 :(得分:0)

尽管这个问题比较老,但是使用Python将PNG文件转换为ICO时,这是一个突出的搜索结果,所以我想我要加两分钱。

如果您想要的只是一个favicon,对我来说,道格拉斯·里德(Douglas Leeder)的答案似乎非常合适。如果您的徽标有一个高分辨率PNG文件,并且想要将其转换为ICO文件,那么RonanPaixão的答案可能是最简单的方法。

但是ICO文件可以包含用于不同分辨率的多个图像,我经常发现自己希望对这些不同分辨率进行细粒度控制,以避免不幸的抗锯齿效果,这意味着我想要单独提供每个图像分辨率。这意味着我不想将单个PNG文件转换为一个ICO文件,而是将多个PNG文件转换为单个ICO文件。据我所知,Pillow软件包不提供此功能。幸运的是,现代ICO文件内部可以包含多个PNG文件,因此该任务归结为编写一些标头条目的简单挑战。根据情况,我编写了两个函数,第一个基本上是RonanPaixão的解决方案,而第二个则提供了将多个PNG文件连接到一个ICO文件中的功能:

from pathlib import Path
from PIL import Image


def bake_one_big_png_to_ico(sourcefile, targetfile, sizes=None):
    """Converts one big PNG into one ICO file.

    args:
        sourcefile (str): Pathname of a PNG file.
        targetfile (str): Pathname of the resulting ICO file.
        sizes (list of int): Requested sizes of the resulting
            icon file, defaults to [16, 32, 48].

    Use this function if you have one big, square PNG file
    and don’t care about fine-tuning individual icon sizes.

    Example::

        sourcefile = "Path/to/high_resolution_logo_512x512.png"
        targetfile = "Path/to/logo.ico"
        sizes = [16, 24, 32, 48, 256]
        bake_one_big_png_to_ico(sourcefile, targetfile, sizes)
    """
    if sizes is None:
        sizes = [16, 32, 48]
    icon_sizes = [(x, x) for x in sizes]
    Image.open(sourcefile).save(targetfile, icon_sizes=icon_sizes)


def bake_several_pngs_to_ico(sourcefiles, targetfile):
    """Converts several PNG files into one ICO file.

    args:
        sourcefiles (list of str): A list of pathnames of PNG files.
        targetfile (str): Pathname of the resulting ICO file.

    Use this function if you want to have fine-grained control over
    the resulting icon file, providing each possible icon resolution
    individually.

    Example::

        sourcefiles = [
            "Path/to/logo_16x16.png",
            "Path/to/logo_32x32.png",
            "Path/to/logo_48x48.png"
        ]
        targetfile = "Path/to/logo.ico"
        bake_several_pngs_to_ico(sourcefiles, targetfile)
    """

    # Write the global header
    number_of_sources = len(sourcefiles)
    data = bytes((0, 0, 1, 0, number_of_sources, 0))
    offset = 6 + number_of_sources * 16

    # Write the header entries for each individual image
    for sourcefile in sourcefiles:
        img = Image.open(sourcefile)
        data += bytes((img.width, img.height, 0, 0, 1, 0, 32, 0, ))
        bytesize = Path(sourcefile).stat().st_size
        data += bytesize.to_bytes(4, byteorder="little")
        data += offset.to_bytes(4, byteorder="little")
        offset += bytesize

    # Write the individual image data
    for sourcefile in sourcefiles:
        data += Path(sourcefile).read_bytes()

    # Save the icon file
    Path(targetfile).write_bytes(data)

该代码假定您的PNG文件是每像素32位RGBA图像。否则,必须更改上面代码中的数字32,并用一些枕头图像嗅探代替。

答案 5 :(得分:0)

我正尝试将我的徽标批量转换为与fbs打包的基于python的应用程序的多种尺寸,并最终根据以上答案使用以下方法来完成此操作。

即使在Windows中生成并显示的.ico文件也可以完美工作。在Linux中,它显示了一个压缩的Icon.ico,但并不担心,因为它只能在Windows中使用。

enter image description here

from PIL import Image
icon_sizes = [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (255, 255)]
image = Image.open('/some/path/to/logo-python/logo.png')
fileoutpath = '/some/path/to/logo-python/'
for size in icon_sizes:
    print(size[0])
    fileoutname = fileoutpath + str(size[0]) + ".png"
    new_image = image.resize(size)
    new_image.save(fileoutname)

new_logo_ico_filename = fileoutpath + "Icon.ico"
new_logo_ico = image.resize((128, 128))
new_logo_ico.save(new_logo_ico_filename, format="ICO",quality=90)