· 5 min read

Jak Animowane GIF faktycznie działa - Od Canvas frames do LZW kompresja

Format GIF ma 39 lat i jest wciąż wszędzie. Oto co się dzieje pomiędzy kliknięciem 'Export' i uzyskaniem pliku - przechwytywanie ramki, kwantyfikacja kolorów, kompresja LZW i dlaczego GIF jest 4MB.

Dlaczego GIF nadal istnieje

Format wymiany graficznej został stworzony przez CompuServe w 1987 roku [CompuServe, 1987]. Obsługuje animację, przejrzystość i bezstratną kompresję. Jest ograniczona do 256 kolorów na ramkę. Nie ma dźwięku. Produkuje duże pliki. Za pomocą wszelkich środków technicznych powinna ona zostać zastąpiona dziesięciolecia temu.

A jednak: Discord, Slack, iMessage, Twitter, Reddit i e-mail wszystkie wsparcie GIF naiwnie. GIPHY obsługuje ponad 10 miliardów GIF dziennie [GIPHY, 2020]. Format utrzymuje się, ponieważ działa wszędzie, nie wymaga kodeka i gra automatycznie. Żaden inny format nie posiada tej kombinacji uniwersalnego wsparcia i odtwarzania tarcia zerowego.

Zrozumienie, jak działają GIF jest przydatne poza ciekawostką - wyjaśnia, dlaczego eksportowany GIF jest 4MB, dlaczego gradienty wyglądają na zaprogramowane i co można z tym zrobić.

Krok 1: Złapanie ramki

Animowany GIF jest sekwencją obrazków (klatek) wyświetlanych z opóźnieniem pomiędzy każdym. Aby stworzyć jeden z animacji płótna, trzeba uchwycić stan płótna w regularnych odstępach czasu.

W przeglądarce oznacza to odczytywanie danych pikseli z elementu HTML <canvas> w każdym czasie ramki - zazwyczaj poprzez canvas.toDataURL() lub ctx.getImageData(). Animacja jest zaawansowana do czasu docelowego, płótno jest renderowane, a piksele są przechwytywane. Kluczowe ograniczenie: należy czekać na cykl malowania przeglądarki (requestAnimationFrame) przed czytaniem pikseli, w przeciwnym razie można uchwycić nieświeży bufor.

Typowy GIF przy 15 FPS przez 3 sekundy wymaga 45 uchwytów ramek. Przy rozdzielczości 1080 × 1080 każda rama wynosi około 4,7 miliona pikseli.

Krok 2: Ilościowanie kolorów

GIF obsługuje maksymalnie 256 kolorów na ramkę, zapisanych w tabeli kolorów (paleta). Typowa rama płótna ma tysiące różnych kolorów. Ograniczenie do 256 bez widocznej degradacji jest najtrudniejszą częścią kodowania GIF.

Standardowym podejściem jest * * mediana cięcia algorytmu * * [Heckbert, 1982]: sortować wszystkie piksele przez ich czerwony kanał, podzielić listę na medianę, powtórzyć dla zielony i niebieski, rekursywnie dzieląc przestrzeń kolorów na 256 regionów. Średnia każdego regionu staje się paletą. To jest to, co gif.js - biblioteka PinePaper wykorzystuje - wdraża w Web Workers dla równoległości [Rubaxa, gif.js].

Quantization kolorów jest powodem, dla którego GIF obsługują grafiki flat- color dobrze, ale zmagają się z fotografiami i gradientami. Gradient w 1080 pikselach może używać 500 + różnych kolorów. Kompresja do 256 zapewnia widoczną kratkę - dyskretne kroki, w których gradient powinien być gładki.

Co możesz z tym zrobić? Użyj mniej kolorów w projekcie. Płaskie kształty, stałe wypełnienie i tekst dobrze się liczą. Gładkie gradienty i tekstury fotograficzne nie. Jeśli Twój GIF ma banding, uprość paletę, a nie rozdzielczość.

Krok 3: Kompresja LZW

Wskaźniki pikseli każdej ramki (odniesienia do palety kolorów 256-) są kompresowane za pomocą * * Lempel- Ziv- Welch * * (LZW) kompresji [Welch, 1984]. LZW buduje słownik powtarzających się sekwencji bajtów podczas skanowania danych. Kiedy napotyka sekwencję, którą widział wcześniej, wychodzi indeks słownika zamiast nierozcieńczonych bajtów.

Oznacza to, że kompresja GIF jest najbardziej skuteczna, gdy istnieją duże obszary powtarzanego koloru - stałe tło, płaskie kształty, tekst na jednolitej powierzchni. Złożone tekstury ze zmiennością poziomu pikseli wytwarzają słabe współczynniki kompresji, ponieważ słownik LZW znajduje kilka powtarzających się sekwencji.

    • Praktyczne implikacje: * * 1080 × 1080 GIF białego tekstu na czarnym tle może skompresować do 200KB. Ta sama rozdzielczość GIF złożonej fotografii może wynosić 8MB. Rozmiar pliku zależy bardziej od złożoności wizualnej niż od rozdzielczości lub liczby klatek.

Krok 4: Usuwanie i optymalizacja ram

Ramki GIF mogą określić metodę usuwania * * *: czy usunąć płótno przed narysowaniem następnej ramki, pozostawić poprzednią ramę widoczną, czy przywrócić do tło. Smart GIF encoders używa * * frame differencing * * - kodowanie tylko pikseli, które zmieniły się między ramami, nie całej ramki.

Jeśli animacja posiada statyczne tło z małym ruchomym elementem, zoptymalizowany GIF koduje tło raz i tylko aktualizuje region, w którym element się porusza. To dramatycznie zmniejsza rozmiar pliku. Enkoder PinePaper wykorzystuje gif.js, który automatycznie stosuje tę optymalizację.

Liczby

Dla typowej animacji PinePaper (1080 × 1080, 15 FPS, 3 sekundy, ciemne tło z animowanym tekstem):

Składnik Rozmiar
Ramki surowe (45 × 4,7M pikseli × 3 bajty) ~634 MB
Po kwantyzacji (256 kolorów, 1 bajt / piksel) ~211 MB
Po kompresji LZW ~2-4 MB
Z odmienną ramą ~1-2 MB

Współczynnik kompresji od surowego do końcowego wynosi około 300: 1 do 600: 1. Większość pochodzi z kwantyfikacji kolorów (3: 1) i LZW (50: 1 do 100: 1).

Kiedy stosować GIF w porównaniu z innymi formatami

Format Najlepsze dla Ograniczenie
GIF Uniwersalne aplikacje wsparcia, autoplay, wiadomości 256 kolorów, duże pliki, brak dźwięku
WebM (VP9) Najlepsza jakość, najmniejsze pliki, internet Ograniczone wsparcie w Safari, iMessage
MP4 (H.264) Media społecznościowe, odtwarzacze wideo Wymaga kodeka, brak przejrzystości
APNG Pełna animacja kolorów z przejrzystością Ograniczone wsparcie w starszych przeglądarkach

GIF jest właściwym wyborem, jeśli potrzebujesz uniwersalnej kompatybilności i samogry. Dla jakości lub wielkości pliku WebM lub MP4 są lepsze.

Spróbuj

Otwórz [PinePaper Studio] (/editor), utwórz projekt i eksportuj jako GIF. Obserwuj jak zmienia się rozmiar pliku:

  • Zwiększ liczbę klatek (więcej klatek = większy plik, proporcjonalnie)
  • Dodaj gradienty (słaba kwantyfikacja = większy plik)
  • Użyj kolorów stałych (dobra kwantyzacja = mniejszy plik)
  • Zwiększ rozmiar płótna (więcej pikseli na ramkę = większy plik)

Każda zmiana jest pomiarem rurociągu kompresji. Nie tylko robisz GIF - obserwujesz, jak teoria informacji odnosi się do twojego projektu.

Odniesienia

  • CompuServe (1987). Grafika Interchange Format Specyfikacja, Wersja 87a.
  • GIPHY (2020). Sprawozdanie roczne GIPHY: 10 miliardów dziennie.
  • Heckbert, P. (1982). Ilościowanie obrazów kolorów dla wyświetlania bufora ramowego. * Grafika komputerowa (SIGGRAPH) *, 16 (3), 297- 307.
  • Rubaxa. gif.js - JavaScript GIF encoder za pomocą Web Workers. github.com / jnordberg / gif.js.
  • Welch, T.A. (1984). A Technique for High- Performance Data Compression. * IEEE Computer *, 17 (6), 8- 19.

Eksport PinePaper GIF jest bezpłatny - bez znaku wodnego, bez rejestracji. Otwórz [pinepaper.studio / editor] (/editor) i eksportuj swoją pierwszą animację.

Ready to create?

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

Open PinePaper Editor