Создание анимированных GIF средствами Java
10К открытий10К показов
Недавно в целях демонстрации работы алгоритма фрактального сжатия мне понадобилось создать GIF-анимацию средствами Java. Стандартная библиотека простого способа это сделать не предоставляла. В связи с этим встала необходимость найти подходящий сниппет. Однако решений в интернете оказалось немного, да и у каждого из них были свои нюансы. С целью облегчить задачу по поиску оптимального решения и была написана эта статья.
Для начала упомяну платное решение — библиотеку Gif4J. Согласно приведенной на главной странице проекта информации, библиотека позволяет не только создавать анимированные GIF-изображения, но и изменять их размер, настраивать цветовой баланс, ставить водяные знаки, получать метаданные из изображений, добавлять текст и т.п. Словом, охватывает весь спектр необходимых действий по работе с GIF-изображениями.
Поиск решения более узкой задачи — поясню, что требуется только создать зацикленную анимацию, состоящую из последовательности изображений одного размера — дал следующие результаты.
Класс GifSequenceWriter, разработанный Эллиотом Кру, который можно скомпилировать и запустить (он содержит метод main
), преобразует несколько файлов одинакового размера в GIF-анимацию. В качестве настроек можно указать, нужно ли зацикливать анимацию или нет, и длительность каждого кадра. Именно им я и воспользовался для решения своей задачи:
Прим. В комментариях в коде неверно описаны параметры:
На самом деле третий параметр задает задержку перед сменой кадра в сотых долях секунды, а четвертый — нужно ли зацикливать анимацию, и значение false
указывает, что зацикливания не будет. Поэтому по умолчанию анимация не зацикливается и кадры сменяются каждую сотую долю секунды.
Коротко поясню, как работает GifSequenceWriter. В нем GIF-файл описывается через метод setAttribute
класса IIOMetadataNode
в соответствии со спецификациями w3.org, после чего результат записывается ImageWriter’ом в выходной файл.
Однако у реализованного подхода есть два недостатка. Во-первых, он совершенно не сжимает выходной файл, а потому его размер оказывается неоправданно большим. Помочь справиться с этой проблемой вам может один из специальных инструментов, доступных онлайн — например, Compressor.io.
Во-вторых, GifSequenceWriter, как и многие другие реализации, не решает проблемы с прозрачными пикселями: в каждом следующем кадре сквозь них просвечивают пиксели предыдущего. Например, вот эти две картинки:
Объединяются в следующую анимацию:
Иногда это может быть неудобно. Для решения этой проблемы существует класс GifFrame. Он индексирует один из цветов как прозрачный (по умолчанию в примере это 0xFF00FF, то есть пурпурный). Результат для вышеупомянутой пары изображений будет иметь следующий вид:
Кстати, в коде, приведенном по ссылке не хватает import
‘ов. Для вашего удобства перечислю их здесь:
Для обеспечения аналогичной функциональности вышеупомянутому классу GifSequenceWriter можете добавить следующий метод main
:
Также набор интересных сниппетов по работе с GIF изображениями на Java приведен по этой ссылке.
10К открытий10К показов