Создание GIF анимации из кадров в Python + Pillow: пошаговая инструкция

Существует множество ситуаций, когда могут быть полезными анимации. Они позволяют сделать приложение более привлекательным для пользователя, сделать его дизайн приятным. А если программа решает коммерческую задачу, то анимации могут непосредственно повлиять на конверсию. Сегодня поговорим об особенностях создания анимаций с помощью библиотеки Pillow для Python.

Когда может использоваться анимация?

К слову, анимация создается не только для красоты. Более того, это – не главное ее назначение. Из-за этого огромное количество людей не понимают, как ее правильно использовать. 

Основная задача анимации – сделать интерфейс удобным. В основе взаимодействия с программой должна быть имитация реального мира. Типичный пример – кнопка. Когда человек ее нажимает, она как бы «проседает» в специальном отсеке.

В компьютерной программе кнопка имеет, по сути, то же назначение, что и в реальном мире. И анимация кнопки была изначально создана для того, чтобы имитировать взаимодействие с реальными объектами, и тем самым сделать приложение интуитивно понятным.

Но даже после отказа от скевоморфизма (дизайнерской концепции, по которой интерфейсы приложений должны были напоминать реальные объекты), анимация остается совместимой с современными программами. Получается реализовать сразу две задачи:

  1. Создать ощущение работы с реальным миром.
  2. Оставить как можно меньше интерфейса, который затрудняет пользовательский опыт. 

Анимация может использоваться в самых разных точках взаимодействия с пользователям:

  1. Приветствия.
  2. Анимация загрузки. Они позволяют наглядно понимать, сколько приблизительно времени осталось до загрузки того или иного приложения. Также они дают возможность понять, что вообще эта загрузка происходит, а не просто зависла программа.
  3. Информативность. Например, анимированные меню могут давать возможность больше информации получить без необходимости дополнительного скроллинга.
  4. Предоставление обратной связи пользователям.
  5. Подсказки и уведомления. Анимация позволяет их выделить на фоне других элементов интерфейса. 

Таким образом, с помощью анимаций можно решать целый спектр практических задач, сделав взаимодействие пользователей с приложением более понятным.

Базовые принципы имитации реального мира

Каким образом анимация имитирует реальный мир? Есть три базовых принципа:

  1. Физическая модель. В ходе разработки интерфейса дизайнеру необходимо создать физическую модель, согласно которой будут двигаться все элементы. Типичный пример такой модели – при наведении мышью на кнопку она заполняется цветом и становится визуально тяжелее. С использованием анимации интерфейса человек понимает, что это – интерактивный элемент.
  2. Контекст, связь. Иллюзия живого взаимодействия создается за счет связи между разными состояниями интерфейса. Например, вы решили почитать книгу. Когда прочитали страницу, вы переворачиваете ее. Это привычно для человека, позволяет связывать одну страницу с другой. Вот анимация перелистывания позволяет создать такую имитацию реального чтения книги.
    Типичный пример хорошей имитации реального мира – «вырастание» приложений из их иконки на рабочем столе в устройствах под управлением iOS и некоторых смартфонах под управлением Android. Это позволяет интуитивно улавливать связь между иконкой программы и непосредственно ее интерфейсом.
  3. Взаимодействие. Те, кто пользовались программой для прогноза погоды на iOS, знают, что там есть анимация грозы или движения туч. Это хорошая логика, поскольку люди привыкли смотреть погоду в окне. Таким образом, программа превращается в реальное окно в реальный мир, где текущая погода видна сразу.

Создание простого GIF из кадров

Самый популярный формат анимированных изображений – GIF. Допустим, у нас есть 10 кадров, где Гомер Симпсон бежит. Наша задача – объединить их в целый GIF-файл. 

Скачать архив можно по ссылке.

Далее наша задача технически сводится к тому, чтобы перебрать каждый кадр. Для этого необходимо воспользоваться циклом for и range. С их помощью мы откроем каждый кадр и добавим его объект в специальный список. 

from PIL import Image

 

# Список для хранения кадров.

frames = []

 

for frame_number in range(1, 11):

    # Открываем изображение каждого кадра.

    frame = Image.open(f'homer/homer-{frame_number}.jpg')

    # Добавляем кадр в список с кадрами.

    frames.append(frame)

 

# Берем первый кадр и в него добавляем оставшееся кадры.

frames[0].save(

    'homer.gif',

    save_all=True,

    append_images=frames[1:],  # Срез который игнорирует первый кадр.

    optimize=True,

    duration=100,

    loop=0

)

Получим такой результат.

Далее мы обсудим все параметры метода save() объекта Image. Но сначала давайте отрегулируем количество времени, в течение которого каждый кадр будет отображаться по отдельности. Для этого у нас существует параметр duration. Ему надо передать список с целочисленными значениями (то есть, время отображения в миллисекундах) для каждого кадра по отдельности. 

frames[0].save(

    'homer-random.gif',

    save_all=True,

    append_images=frames[1:],

    optimize=True,

    duration=[100, 150, 200, 400, 500, 600, 700, 800, 900, 1000], # Разное время отображения для кадров.

    loop=0

)

Теперь наш Гомер начал бегать медленнее. Но обратите внимание, что в нашей анимации теперь он бегает сначала медленно, а потом ускоряется. Все потому, что первые три кадра имеют по 100, 150 и 200 миллисекунд на отображение соответственно. А все остальные также отображаются все меньшее количество времени.Создание GIF анимации из кадров в Python + Pillow: пошаговая инструкция

Использование метода Image.save() для сохранения GIF-файла

Метод Image.save используется для того, чтобы создать из нескольких картинок одну анимированную в формате GIF. 

im.save('out.gif', save_all=True, append_images=[im1, im2, ...])

Список с изображениями [im1, im2, …] прикрепляется к первому кадру, а далее из всех этих картинок создается анимация. В нашем случае файл будет называться out.gif, поскольку именно это имя находится в качестве первого аргумента этого метода.

А теперь давайте разберем пример кода, в котором будут описаны все параметры.

Генерация анимированной картинки

Теперь давайте рассмотрим такой код. Он предназначен для рисования круга, который будет становиться все больше и больше. Для этого нам надо задействовать библиотеку ImageDraw из библиотеки PIL.  

from PIL import Image, ImageDraw




images = []




width = 200

center = width // 2

color_1 = (0, 0, 0)

color_2 = (255, 255, 255)

max_radius = int(center * 1.5)

step = 8




for i in range(0, max_radius, step):

    im = Image.new('RGB', (width, width), color_1)

    draw = ImageDraw.Draw(im)

    draw.ellipse((center - i, center - i, center + i, center + i), fill=color_2)

    images.append(im)




for i in range(0, max_radius, step):

    im = Image.new('RGB', (width, width), color_2)

    draw = ImageDraw.Draw(im)

    draw.ellipse((center - i, center - i, center + i, center + i), fill=color_1)

    images.append(im)




images[0].save(

    'pillow_imagedraw.gif',

    save_all=True,

    append_images=images[1:],

    optimize=False,

    duration=40,

    loop=0

)

Также этот код сохраняет GIF-файл.

Метод Image.save() – параметры

В результате, если у нас имеется список изображений, то с помощью этого кода появляется возможность создать анимированную картинку. 

images[0].save(

    'pillow_imagedraw.gif',

    save_all=True,

    append_images=images[1:],

    optimize=False,

    duration=40,

    loop=0

)

Если вам нужно сгенерировать GIF-файл (гифку) из нескольких картинок, которые уже существуют вместо того, чтобы рисовать картинку так, как в приведенном выше примере, то то же самое можно сделать путем загрузки изображений и последующего добавления их в список.

append_images – как использовать этот параметр?

Для этого нам нужно вызвать метод save() и передать список с другими изображениями параметру append_images.

Учтите, что, если вы напишете append_images=images, в этом случае будет осуществляться повторение первого кадра два раза. В приведенном выше фрагменте кода вторая картинка и все, которые будут следовать за ней, выбираются с помощью среза images[1:].

optimize

Этот параметр отвечает за то, нужно ли сжимать палитру. Если его значение – True, то Pillow удалит неиспользуемые цвета, и таким образом попробует уменьшить количество доступных вариантов. Это поможет уменьшить вес изображения.

loop

Этот параметр отвечает за количество циклов, выполняющихся GIF-анимацией. Можно сделать цикл бесконечным. Для этого необходимо указать значение этого параметра 0.

Учтите то, что стандартно установлен один цикл для анимации. Следовательно, оптимальное значение составляет именно 0.

duration

Этот параметр отвечает за то, сколько времени будет отображаться на экране каждый кадр. Указывать его нужно в миллисекундах. Если величина этого значения будет небольшой, то оно просто будет игнорироваться.

Ему можно передать список с индивидуальной продолжительностью отображения для каждого отдельного кадра в приложении.

Выводы

Таким образом, работа с анимацией – это вовсе несложно. Не нужно сильно затруднять этот процесс, задавая миллионы строк кода. Достаточно лишь сгенерировать готовую анимацию, а дальше ее можно использовать.

Это же позволяет создавать целый класс программ, таких как приложения для создания мультфильмов.

Во многих случаях программа не будет нормально работать без анимации. Конечно, с ней нужно быть осторожным, поскольку чрезмерное количество различных эффектов может привести к, наоборот, затруднению использования программы. Тем не менее, если все делать правильно, можно добиться неплохих результатов.

ОфисГуру
Adblock
detector