Есть ли библиотека Python для генерации.ico файлов?

Я ищу, чтобы создать favicon.ico файлы программно из Python, но PIL поддерживает только чтение ico файлы.

5 ответов

Решение

Согласно Википедии, современные браузеры могут обрабатывать значки в формате PNG, так что, может быть, вы могли бы просто сгенерировать это?

Альтернативно статья ICO описывает формат...

Вы можете использовать подушку:

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 говорят, что по умолчанию он генерирует размеры [(16, 16), (24, 24), (32, 32), (48, 48), (64, 64), (128, 128), (255, 255)] и любой размер больше исходного размера или 255 будет игнорироваться.

Да, он находится в разделе " Только для чтения " документации, но в некоторой степени работает.

Возможно, будет работать следующее:

  • Создайте изображение значка с помощью PIL
  • Преобразование изображения в формат.ico с использованием интерфейса Python для ImageMagick, PythonMagick

Я не пробовал этот подход. Программа командной строки ImageMagick convert смогла преобразовать файл.png в формат.ico, поэтому, по крайней мере, ImageMagick поддерживает формат.ico.

Хотя этот вопрос довольно старый, это выдающийся результат поиска по использованию Python для преобразования файлов PNG в ICO, поэтому я решил добавить свои два цента.

Если все, что вам нужно, это фавикон, ответ Дугласа Лидера мне кажется идеальным. Если у вас есть один PNG-файл с высоким разрешением вашего логотипа и вы хотите преобразовать его в файл ICO, ответ Ронана Пайшё, вероятно, будет самым простым способом.

Но файл ICO может содержать несколько изображений, предназначенных для разных разрешений, и я часто оказывался в ситуации, когда мне хотелось иметь точный контроль над этими различными разрешениями, чтобы избежать нежелательных эффектов сглаживания, что означает, что я хочу предоставить разрешение каждого изображения индивидуально. Это означает, что я хочу преобразовать не один, а несколько файлов PNG в один файл ICO. Насколько я понимаю, пакет Pillow не предоставляет такой возможности. К счастью, современный файл ICO может содержать внутри несколько файлов PNG, поэтому задача сводится к простой задаче написания некоторых записей заголовков. В зависимости от ситуации я написал две функции, первая из которых в основном является решением Ронана Пайшё, а вторая обеспечивает функциональность для объединения нескольких файлов 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 представляют собой изображения RGBA с 32-битным разрешением. В противном случае число 32 в приведенном выше коде пришлось бы изменить и заменить на какое-нибудь обнюхивание подушечки.

Если у вас есть imageio(вероятно, лучшая библиотека для чтения / записи изображений в Python), вы можете использовать ее:

import imageio

img = imageio.imread('logo.png')
imageio.imwrite('logo.ico', img)

Установить так же просто, как

pip install imageio

Я не знаю, применимо ли это ко всем случаям, но в WinXP.ico может иметь размер 16x16, 32x32 или 64x64. Просто измените расширение на ico с bmp, и вы готовы к работе.

Я пытался пакетно преобразовать свой логотип в несколько размеров для моего приложения на основе Python, упакованного с помощью fbs, и в итоге использовал приведенное ниже, чтобы сделать это на основе приведенных выше ответов.

отлично работал, даже сгенерированный.ico и показанный в Windows. В Linux он показывает один Icon.ico как сжатый, но не особо беспокоясь об этом, поскольку он будет использоваться только в Windows.

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)
Другие вопросы по тегам