· 5 min read

Как на самом деле работают анимированные GIF-файлы — от холстовых кадров до сжатия LZW

Формату GIF 39 лет и он до сих пор существует. Вот что происходит между нажатием «Экспорт» и получением файла — захват кадра, квантование цвета, сжатие LZW и почему ваш GIF составляет 4 МБ.

Почему GIF все еще существуют

Формат обмена графикой был создан CompuServe в 1987 году. Он поддерживает анимацию, прозрачность и сжатие без потерь. Он ограничен 256 цветами на кадр. У него нет аудио. Он создает большие файлы. По всем техническим меркам его следовало заменить десятилетия назад.

И все же: Discord, Slack, iMessage, Twitter, Reddit и электронная почта поддерживают GIF. GIPHY обслуживает более 10 миллиардов GIF в день [GIPHY, 2020]. Формат сохраняется, потому что он работает везде, не требует кодека и воспроизводится автоматически. Ни один другой формат не имеет такого сочетания универсальной поддержки и воспроизведения с нулевым трением.

Понимание того, как работают GIF-файлы, полезно помимо мелочей — это объясняет, почему экспортируемый вами GIF составляет 4 МБ, почему градиенты выглядят полосатыми и что вы можете с этим сделать.

Шаг 1: захват кадра

Анимированный GIF представляет собой последовательность изображений (кадров), отображаемых в порядке с задержкой между каждым из них. Чтобы создать один из анимации холста, вам нужно захватить состояние холста через регулярные промежутки времени.

В браузере это означает чтение пиксельных данных из элемента HTML <canvas> в каждый момент кадра — обычно через canvas.toDataURL() или ctx.getImageData(). Анимация продвигается до целевого времени, холст визуализируется, а пиксели захватываются. Ключевое ограничение: вы должны дождаться цикла окраски браузера (requestAnimationFrame) перед чтением пикселей, иначе вы захватите несвежий буфер.

Типичный GIF при 15 FPS в течение 3 секунд требует 45 кадровых захватов. При разрешении 1080×1080 каждый кадр составляет примерно 4,7 миллиона пикселей.

Шаг 2: Количественное определение цвета

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

Стандартным подходом является алгоритм median cut [Heckbert, 1982]: сортируйте все пиксели по их красному каналу, разделите список по медиане, повторите для зеленого и синего, рекурсивно разделив цветовое пространство на 256 областей. Средний показатель каждого региона становится входной палитрой. Это то, что gif.js — библиотека PinePaper — реализует в Web Workers для параллелизма [Rubaxa, gif.js].

Цветовое квантование — это то, почему GIF-файлы хорошо справляются с плоскоцветной графикой, но борются с фотографиями и градиентами. Градиент в 1080 пикселей может использовать более 500 различных цветов. Сжатие до 256 создает видимую полосу - дискретные ступени, где градиент должен быть гладким.

Что можно с этим сделать: Используйте меньше цветов в дизайне. Плоские формы, твердые наполнители и текст хорошо количественно. Гладких градиентов и фотографических текстур нет. Если ваш GIF имеет полосы, упростите палитру, а не разрешение.

Шаг 3: Сжатие LZW

Индексы пикселей каждого кадра (ссылки на 256-цветную палитру) сжимаются с помощью сжатия Lempel-Ziv-Welch (LZW) [Welch, 1984]. LZW создает словарь повторяющихся последовательностей байтов при сканировании данных. Когда он сталкивается с последовательностью, которую он видел раньше, он выводит словарный индекс вместо необработанных байтов.

Это означает, что сжатие GIF наиболее эффективно, когда есть большие участки многократного цвета — сплошные фоны, плоские формы, текст на однородной поверхности. Сложные текстуры с вариациями на уровне пикселей создают плохие коэффициенты сжатия, потому что словарь LZW находит несколько повторяющихся последовательностей.

Практические последствия: 1080×1080 GIF белого текста на черном фоне может сжиматься до 200 КБ. То же разрешение GIF сложной фотографии может составлять 8 МБ. Размер файла зависит больше от визуальной сложности, чем от разрешения или количества кадров.

Шаг 4: Удаление и оптимизация кадров

Рамки GIF могут указывать метод удаления: следует ли очистить холст перед рисованием следующего кадра, оставить предыдущий кадр видимым, или восстановить его. фон. Смарт-кодеры GIF используют frame differentencing — кодирование только пикселей, которые изменились между кадрами, а не всего кадра.

Если ваша анимация имеет статический фон с небольшим движущимся элементом, оптимизированный GIF кодирует фон один раз и обновляет только область, в которой перемещался элемент. Это значительно уменьшает размер файла. Кодер PinePaper использует gif.js, который автоматически применяет эту оптимизацию.

Числа

Для типичной анимации PinePaper (1080×1080, 15 FPS, 3 секунды, темный фон с анимированным текстом):

Компонент Размер
Сырые кадры (45 × 4,7 M пикселей × 3 байта) ~634 MB
После квантования (256 цветов, 1 байт/пиксель) ~211 MB
После сжатия LZW ~2-4 MB
С дифференциацией кадров ~1-2 MB

Соотношение сжатия от сырого до конечного составляет приблизительно 300:1 до 600:1. Большая часть этого происходит от квантования цвета (3:1) и LZW (50:1 до 100:1).

Когда использовать GIF против других форматов

Формат Лучшее для Ограничение
GIF Универсальная поддержка, авто-игра, приложения для обмена сообщениями 256 цветов, большие файлы, без звука
WebM (VP9) Лучшее качество, самые маленькие файлы, Интернет Ограниченная поддержка в Safari, iMessage
MP4 (H.264) Социальные сети, видеоплееры Требуется кодек, нет прозрачности
АНГ Полноцветная анимация с прозрачностью Ограниченная поддержка в старых браузерах

GIF — это правильный выбор, когда вам нужна универсальная совместимость и автоматическое воспроизведение. Для качества или размера файла лучше использовать WebM или MP4.

Попробуйте

Откройте [PinePaper Studio] (/editor), создайте дизайн и экспортируйте как GIF. Посмотрите, как меняется размер файла:

  • Увеличение количества кадров (больше кадров = больший файл, пропорционально)
  • Добавить градиенты (плохое квантование = больший файл)
  • Используйте сплошные цвета (хорошее квантование = меньший файл)
  • Увеличение размера холста (больше пикселей на кадр = больше файла)

Каждое изменение представляет собой измерение трубопровода сжатия. Вы не просто создаете GIF — вы наблюдаете, как теория информации применима к вашему дизайну.

Ссылки

  • CompuServe (1987). Спецификация формата обмена графикой, версия 87a.
  • Гиффи (2020). Годовой отчет GIPHY: 10 миллиардов ежедневных слуг.
  • Хекберт П. (1982). Количественное значение цветного изображения для фрейм-буферного дисплея. Компьютерная графика (SIGGRAPH), 16(3), 297-307.
  • Rubaxa. gif.js — кодер JavaScript GIF с использованием Web Workers. github.com/jnordberg/gif.js.
  • Уэлч, Т.А. (1984). Метод высокопроизводительного сжатия данных. IEEE Computer, 17(6), 8-19.

Экспорт PinePaper GIF бесплатен - нет водяного знака, нет регистрации. Откройте [pinepaper.studio/editor] (/editor) и экспортируйте свою первую анимацию.

Ready to create?

Start making animated GIFs, videos, and graphics — free, no signup.

Open PinePaper Editor