Formaty obrazu: GIF

Choć format GIF (Graphics Interchange Format) nie jest zbyt przydatny we współczesnym internecie, stanowi dobre wprowadzenie do podstawowych koncepcji kodowania obrazów.

Plik GIF można określić jako kod do pliku graficznego. Zawiera widoczny obszar, nazywany „ekranem logicznym”, do którego są rysowane poszczególne ramki danych obrazu. Jest to coś w rodzaju warstw w dokumencie w Photoshopie. W ten sposób GIF obsługuje swoją animację w formie kineografu: na ekranie logicznym jest rysowana pojedynczą klatkę, zastępowaną kolejną, a potem kolejną. Oczywiście to rozróżnienie nie ma znaczenia, gdy mamy do czynienia ze statycznym plikiem GIF, który składa się z pojedynczej klatki pobranej do logicznego ekranu.

GIF używa metody bezstratnej kompresji danych – wariantu algorytmu „Lempel–Ziv–Welch” (jeśli Cię to interesuje). Szczegółowe informacje o działaniu tego algorytmu nie są nam potrzebne, ale ogólnie rzecz biorąc: działa on trochę jak „poprawiający” kod JavaScript, w którym powtarzające się ciągi znaków z całego pliku są zapisywane w słowniku wewnętrznym, dzięki czemu nie trzeba powtarzać tych znaków za każdym razem, gdy się pojawią.

Wizualizacja odniesienia do GIF-a w postaci siatki cztery na cztery.

Oczywiście algorytm nie jest tak prosty jak malowanie po liczbach. Ponownie sprawdza wygenerowaną tabelę kodów kolorów, aby znaleźć powtarzające się sekwencje kolorów pikseli, i tworzy drugą tabelę z kodami, do których można się odwoływać. Jednak w żadnym momencie nie dochodzi do utraty żadnych danych dotyczących zdjęć – wystarczy je posortować i uporządkować w taki sposób, aby można je było odczytać bez konieczności wprowadzania zmian.

Chociaż GIF korzysta z bezstratnej kompresji, ma on poważne ograniczenie, które znacznie wpływa na jakość obrazów. Zapisanie obrazu w pliku GIF zawsze powoduje pogorszenie jakości, chyba że używa on już maksymalnie 256 kolorów.

Każda ramka wyświetlana na ekranie logicznym GIF może zawierać maksymalnie 256 kolorów. GIF obsługuje też „przezroczystość indeksu”, gdzie przezroczysty piksel będzie odwoływać się do indeksu przezroczystego „koloru” w tabeli kolorów.

Zmniejszanie zakresu wartości do mniejszego, przybliżonego zbioru wartości wyjściowych nazywane jest kwantyzacją. Terminem, na który można zwracać uwagę podczas poznawania kodowania obrazów, można często zauważyć. Wyniki tej kwantyzacji palety są zwykle oczywiste:

Przykład statycznego GIF-a

Aby lepiej zrozumieć ten proces, wróć do siatki obrazów rastrowych, które udało Ci się odtworzyć z mojego opisu.

3 poziome niebieskie pola, a po nich 1 czerwona

Tym razem dodaj więcej szczegółów do oryginalnego zdjęcia: jeszcze kilka pikseli. Jeden z nich to nieco ciemniejszy odcień niebieskiego:

Niebieskie do czerwonych poziomych ułożone w zestawie dwa na cztery, przy czym jedno niebieskie pole jest ciemniejsze od innych.

Siatka nie jest kompresowana, tzn. można opisać ją następująco:

Wiersz pierwszy, kolumna pierwsza to #0000FF. Wiersz pierwszy, druga kolumna to #0000FF. Wiersz pierwszy, trzecia kolumna to #0000FF. Wiersz 1, kolumna 4 to #FF0000. Wiersz drugi, kolumna pierwsza to #0000FF. Wiersz 2, 2 kolumna to #000085. Wiersz 2, kolumna trzecia to #0000FF. Wiersz 2, kolumna 4 to #FF0000.

Wykorzystanie czegoś podobnego do bezstratnej kompresji danych i indeksowania kolorów GIF-a można opisać następująco:

A: #0000FF, B: #FF0000, C: #000085. Wiersz 1, kolumny od 1 do 3 to A. Wiersz 1, kolumna 4 to B. Wiersz 2, 1 kolumna to A. Wiersz 2, 2 kolumna to C. Wiersz 2, kolumna 3 to A. Wiersz 2, kolumna 4 to B.

Pozwala to zagęścić opis piksel po piksela w kilku miejscach („kolumny od 1 do 3 to...”) i zaoszczędzi kilka znaków, definiując z wyprzedzeniem powtarzane kolory w słowniku. Jakość obrazu nie uległa zmianie. Informacje zostały skompresowane bez utraty danych.

Poziome prostokąty od niebieskiego do czerwonego z pojedynczym ciemnym pikselem o wymiarach 2 x 2.

Jak widać, pojedynczy ciemnoniebieski piksel ma ogromny wpływ na rozmiar naszego kodowania. Gdyby miałbym ograniczyć się do poddanej kwantyzacji palety kolorów, mógłby on zostać znacznie bardziej ograniczony:

A: #0000FF, B: #FF0000. Wiersz 1, kolumny od 1 do 3 to A. Wiersz 1, kolumna 4 to B. Wiersz 2; kolumny od 1 do 3 to A. Wiersz 2, kolumna 4 to B.

W rezultacie te bajty są niedoskonałe, co powoduje utratę ich doskonałości.

Poziome pola o równym kolorze niebieskim do czerwonych.

Oczywiście, mechanizm renderujący nie wie, że szczegóły ciemniejszego niebieskiego piksela nie zostały uwzględnione w kodzie obrazu źródłowego. Obraz został wyrenderowany dokładnie w takiej postaci, w jakiej zakodowałem go na podstawie naszej wiedzy o kolorach, którymi dysponujemy.

W tym przesadnym przykładzie zmniejszenie trzech kolorów do dwóch daje oczywistą zmianę jakości. Na większym i bardziej szczegółowym zdjęciu efekty mogą nie być tak widoczne, ale nadal będą widoczne.

Przy zakodowaniu jako plik GIF subtelne gradienty, takie jak cienie, stają się plamkami, a pojedyncze piksele wyróżniają się z otoczenia:

Różowe kwiaty na zielonym tle.

W praktyce połączenie bezstratnej kompresji i kwantyzacji palety sprawia, że pliki GIF nie są zbyt przydatne we współczesnym tworzeniu stron internetowych. Kompresja bezstratna nie wystarczy, aby zmniejszyć rozmiar plików, a zmniejszona paleta oznacza oczywiste obniżenie jakości.

W ostatecznym rozrachunku GIF jest skutecznym formatem do kodowania prostych obrazów, które mają już ograniczoną paletę kolorów, twarde krawędzie (zamiast antyaliasingu) i kolory jednolity zamiast gradientów. Wszystkie przypadki użycia są znacznie lepsze od innych formatów. Mniejszy i bardziej polecany plik PNG jest często lepszym wyborem w przypadku obrazów rastrowych, choć oba z nich są znacznie gorsze od SVG pod względem rozmiaru i jakości wizualnej w przypadku użycia takich jak ikony czy grafika liniowa, gdzie wektorowy błyszczą. Najczęściej stosowanym nowoczesnym zastosowaniem GIF-ów jest animacja. Istnieją też jednak znacznie bardziej wydajne i przystępne formaty wideo, które służą do tego celu.