· 6 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).

Нажмите на четыре этапа. Брусок нарисован против сырого размера на одном линейная шкала, поэтому на последних двух этапах это линия волос это не является в этом и заключается смысл 300:1.

Interactive demo — open in editor pp:PinePaper

Когда использовать 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). Количественное представление цветового изображения для Frame Buffer Display. Компьютерная графика (SIGGRAPH)*, 16(3), 297-307.
  • Рубакса. 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