Najpopularniejszymi standardami stosowanymi w Internecie są GIF oraz JPEG. Biorąc pod uwagę ich wady i zalety wykorzystywane one są w zależności od aktualnej potrzeby.

Format GIF

GIF został zaprezentowany przez firmę Compuserve w roku 1987, i stał się światowym standardem jeśli chodzi o kodowanie dużej liczby generowanych komputerowo i skanowanych obrazów. Format ten jest jednym z najczęściej stosowanych formatów używanych do kolorowych map bitowych, ponieważ sam standard zapisu jest bardzo dobrze udokumentowany, dzięki czemu bardzo łatwo zaimplementować odpowiednie algorytmy w wielkiej liczbie programów. Standard ten sam w sobie jest stosunkowo prosty i posiada niewielką liczbę wariantów ( te używane najczęściej do GIF 87 i GIF 89 ). Obrazy w formacie GIF zawierać mogą przeplot i w wypadku takim zapisywane one są w następującej kolejności: na początku, co ósmy rząd obrazu, następnie, co czwarty, co drugi i w końcu nieparzyste wiersze. Dzięki temu można pokazywać w bardzo dobry sposób obrazy przesyłane w kolejnych przybliżeniach przez Internet. Format ten zawiera również klatki prostych animacji. Każda z klatek jest pojedynczym obrazem oddzielonym przecinkiem od kolejnego obrazu. GIF stanowi dosyć prosty format mapy bitowej. Najważniejszą cechą plików GIF jest fakt, że piksele pakowane są przy użyciu kompresji słownikowej LZW. Sama kompresja LZW jest kompresją wyjątkowo efektywną w przypadku obrazów o powtarzających się wzorach pikseli, nawet powtarzających się czystych plam kolorystycznych. Znacznie gorzej format ten sprawdza się w kompresji skanowanych i skomplikowanych obrazów, ale nawet pomimo tego kompresja LZW stanowi najskuteczniejszą bezstratną kompresję obrazu. Pewną wadą plików GIF jest fakt, że mogą one zawierać maksymalnie 256 różnych kolorów i wymagają wtedy 8 bitów na każdy piksel. Jeżeli zmniejszymy liczbę kolorów liczba bitów wymaganych do opisania koloru piksela znacznie się zmniejsza.

Budowa pliku GIF

Plik GIF zaczyna się od nagłówka i opcjonalnej globalnej mapy kolorów, która używana jest dla każdego zawartego w pliku obrazu. Po części początkowej znajdujemy pojedynczy lub większą ilość obrazów, z których każdy składa się z bloku opisu danego obrazu, opcjonalnej mapy kolorów lokalnych oraz danych skompresowanych.

Kodowanie GIF

Poszczególne obrazy w plikach GIF rozdzielone są między sobą przecinkami, a kończą się średnikiem. Każdy z obrazów rozpoczyna się przecinkiem a następnie nagłówkiem obrazu. Nagłówek znajduje się na pozycji lewego, górnego rogu obrazu, biorąc pod uwagę brzegi ekranu. Znajduje się tam również bajt znaczników, który zawiera dane o przeplocie. W kolejnym bajcie podany jest minimalny rozmiar słowa kodu kompresji LZW, a następnie znajdujemy sam obraz. Plik GIF jest zakończony średnikiem, który oznacza brak dalszych obrazów.

Kompresja LZW

Kompresja LZW polega na budowaniu słownika ciągów pikseli. Każdy z ciągów w słowniku identyfikowany jest wartością kodu, a rezultat tej operacji stanowi lista kodów ze słownika. Kompresor służy do budowania słownika w locie. Przykładowo załóżmy, że każdy z pikseli jest 4 - bitowy i przyjmuje możliwe wartości z zakresu od 0 do 15. Zaczniemy od ustawienia na pozycjach od 0 do 15 w naszej tabeli kodów ciągów jedno-pikselowych, kodowi 0 odpowiada więc ciąg złożony z jednego piksela o wartości 0, kodowi 1 odpowiada ciąg złożony z piksela o wartości 1 i tak dalej. Kod 16 rezerwowany jest jako kod czyszczący, natomiast kod 17 jako kod końca pliku. Kolejny nieużywany kod stanowi więc liczba 18. W momencie, kiedy kompresor graficzny czyta piksele, odnajduje najdłuższy ciąg pikseli w pliku, który pasuje do jednej z pozycji w słowniku. Ma zatem w każdej chwili próbne dopasowanie ciągu pikseli, które zostały już wczytane, a dla których kodu nie wysłano jeszcze na wyjście. W każdej chwili, gdy kompresor wczytuje kolejny piksel wykonywane są następujące operacje:

  • Piksel jest dodawany do ciągle próbkowanego dopasowanego ciągu i sprawdza się czy w słowniku nie istnieje już jakieś dopasowanie do nowo powstałego ciągu próbnego. Jeżeli tak, kod, który odpowiada nowemu ciągowi próbnemu, jest zapamiętywany i kompresor przechodzi do kolejnego piksela.
  • Jeżeli nowy ciąg próbny nie zostanie odnaleziony w słowniku, wysyłany na wyjście jest kod starego ciągu. Potem nowy ciąg próbny, na który składa się ciąg stary i dopiero co wczytany piksel, umieszczany jest w słowniku dla użytku w przyszłości. Stary ciąg usuwany jest ze słownika i cały proces rozpoczyna się na nowo, wraz z nowym próbnym dopasowywanym ciągiem, który składa się z pojedynczego, dopiero co przeczytanego piksela.

Kompresor w kółko powtarza ten proces, aż do momentu, w którym przeczyta on wszystkie dane wyjściowe. Na koniec zapisywany jest kod ostatniego dopasowania próbnego oraz kod oznajmiający koniec pliku.

Format JPEG

Drugim z najpopularniejszych formatów graficznych używanych w Internecie jest format JPEG, którego rozszerzenie oznacza się literami .jpg. JPEG stanowi bardzo wyrafinowany format zapisu map bitowych. Instrukcje kompresora tego formatu zajmują dwustu stronicową książkę. Skrót JPEG wziął stoją nazwę od Joint Photographic Experts Group, czyli od Wspólnej Grupy Rzeczoznawców Fotografii. Grupa ta pracowała nad standardem graficznym w ramach organizacji ISO - International Organization for Standarization. JPEG w zamierzeniach swoich twórców miał stać się standardowym formatem kompresji dla cyfrowej fotografii, tak też stało się w istocie. Przeciwnie do formatu GIF, format JPEG to format stratny, co znaczy, że nie da się idealnie zrekonstruować oryginalnego kolorowego obrazu. Pomimo tej stratności formatu, obraz z pliku JPEG bardziej przypomina obraz oryginalny, niż plik bezstratnego formatu GIF. Przyczyną tego stanu rzeczy, jest fakt, że format GIF służy do zapisywania obrazów w 256 kolorowej palecie barw. GIF również więc nie odtworzy oryginalnego obrazu w pełnym kolorze. Mapowanie kolorów powoduje w istocie znacznie większa stratę jakości obrazu w plikach GIF o tym samym obrazie co odpowiadające im obrazy JPEG. W przeciwieństwie do GIF, format JPEG umożliwia zmianę wielkości oraz jakości danego obrazu. Przyjmuje się, że JEG jest w stanie zakodować w dobrej jakości grafikę używając przy tym tylko 1 bitu na pojedynczy piksel.

Istnieją rodzaje obrazów, które nie są odpowiednie dla formatu JPEG. Z powodu tego, że format ten zaprojektowano do obsługi cyfrowych fotografii, nie radzi on sobie dobrze z krawędziami ostrymi, które są charakterystyczne dla obrazów oraz wykresów tworzonych komputerowo. Nie nadaje się on również do kompresowania dużych płaszczyzn powierzchni o takim samym kolorze. JPEG zaprojektowano z myślą o standardzie kodowania strumieni danych, nie zaś pojedynczego pliku. Dekodowanie sprzętowe JPEG powinno być na tyle szybkie, aby zdekodować dany obraz już w czasie jego odbierania z Internetu. Format JPEG posiada kilka specjalnych odmian, które umożliwiają wyświetlenie danego obrazu w bardzo niskiej rozdzielczości oraz poprawienie obrazu w czasie dalszego jego odbierania. Ściągając z Internetu pliki graficzne widzimy jak powoli krystalizują się one na ekranie.

Inne formaty JPEG

Istnieje kilka głównych formatów zapisu plików JPEG. Prostszy z nich znany jest pod nazwą JFIF i składa się on ze strumienia z danymi JPG oraz kilkoma elementami obowiązkowymi, dzięki którym obrazy skompresowane w JFIF mogą być rozkodowywane bez dodatkowego ściągania zewnętrznych danych, są one jednak bardzo rzadko spotykane w Internecie.

Kolejnym formatem kompresji jest odmiana RIFF, która została wprowadzona wraz ze specyfikacja TIFF 6.0, i która służy do osadzenia obrazu JPEG podzielonego w miarę możliwości na kafelki i paski w pliku TIFF. Opisywany format znany jest pod nazwą JPEG - w - TIFF i nie jest zbyt popularny, głównie za sprawą swojego skomplikowania i zarazem niewiele większej użyteczności od formatu JFIF. Od kodowania TIFF różni go jedynie to, że dekompresory TIFF nie są w stanie sobie z nim poradzić.

Kodowanie JPEG

Zamiana obrazu 24 - bitowego na strumień danych w formacie JPEG odbywa się w czterech etapach:

  • Zakodowanie koloru,
  • Użycie dyskretnej transformacji cosinusowej - DCT,
  • Kwantyzacja otrzymanych próbek,
  • Kodowanie próbek skwantowanych.

Pierwszym krokiem w stratnej kompresji obrazu pełno - kolorowego jest odpowiednie zakodowanie kolorów. Krok ten jest opcjonalny, jednak pozwala na zaoszczędzenie aż 50% rozmiaru pliku wynikowego, dlatego jest prawie zawsze wykorzystywany. Ludzkie oko jest znacznie bardziej wyczulone na jasność obrazu niż na jego barwę. Jeżeli zatem będziemy w stanie odpowiednio przekształcić dane przechowywane w kanałach RGB, w taki sposób, aby przewołać jasność piksela w jednej składowej, a kolory w dwóch pozostałych, to możliwe staje się usunięcie dużej części informacji o kolorze, bez widocznego pogorszenia jakości oglądanego obrazu. Najczęściej stosowanym formatem kodowania koloru jest układ YCbCr, który oparty jest na używanym w telewizji układzie. Poszczególne komponenty obrazu składają się ze składowych podstawowych i oznaczają kolejno:

  • Luminację piksela Y = 0,299 R + 0,587 G + 0,114 B,
  • Chrominancję niebieską Cb = -0,1687 R - 0,3313 G + 0,5 B,
  • Chrominancję czerwoną Cr = 0,5 R - 0,4187 G - 0,0813 B.

Kodowanie koloru jest jeszcze zmianą bezstratną obrazu, ponieważ poszczególne wartości RGB mogą być bez problemu odtworzone dzięki odwróceniu procesów arytmetycznych. W momencie, w którym będziemy już mieli poszczególne składowe YCbCr, zmniejszamy gęstość informacji o obrazie przez tak zwane podpróbkowanie. Polega ono na odpowiednim uśrednieniu składowych wartości chrominancji dla każdego z bloków 2x2 piksele. Co za tym idzie każdy blok 2x2 piksele jest opisany czterema wartościami Y oraz jedną wartością Cb oraz Cr. Zamiast dwunastu składowych jak w przypadku kolorów w standardzie RGB otrzymujemy sześć składowych, z których każda traktowana jest później jako oddzielny płat obrazu i jest ona następnie oddzielnie kompresowana i przekształcana. Kodowania kolorów nie stosuje się w obrazach o skali szarości. W wypadku tym każda wartość piksela jest bezpośrednio poddawana transformacji DCT.

Następnym etapem kompresji JPEG jest transformacja DCT obrazu. DCT wzięło swoją nazwę od Discrete Cosinus Transform, czyli od Dyskretnej Transformacji Cosinusowej. Transformacja ta wykorzystuje fakt, że ludzkie oko jest o wiele bardziej czułe na stopniowe zmiany koloru i jasności niż na zmiany nagłe. Dzięki użyciu DCT przejścia pomiędzy barwami są dyskretne. Transformacja bierze blok złożony z 8x8 komponentów a następnie wykonuje transformację cosinusową, której wynikiem jest częstotliwościowe przedstawienie obrazu. Składowa (0,0) otrzymanego rezultatu opisuje niezmienność składowych wejściowych i jest równoznaczna z wartością średnią tych składowych. Składowe o numerach większych odpowiadają wyższym częstotliwościom obrazu, reprezentujących szybsze zmiany barwy i jasności obrazu.

DCT stanowi w dalszym ciągu transformację bezstratną. Dzięki użyciu transformacji DCT można odtworzyć poszczególne wartości komponentów obrazu otrzymując pierwowzór. Nieidealna transformata DCT, która jest realizowana może spowodować, że odtworzony obraz będzie się nieco różnił, jednak zmiany te będą niedostrzegalne dla ludzkiego oka. Znacznie większe różnice w oglądanym obrazie są zasługa procesu kwantyzacji.

Kwantyzacja stanowi główny etap stratny w czasie kodowania JPEG. Każda wartość wyjściowa powstała wskutek transformacji DCT jest liczbą całkowitą 12 - bitową. Dowolny obraz JPEG posiada tablicę kwantyzacyjną o rozmiarach 8x8, która jest tablicą wartości, przez które zostaną podzielone odpowiednie wartości transformacji DCT. Dekoder dostaje identyczną tablicę z pliku obrazu, w którym została ona zapisana, a następnie mnoży odpowiednią pozycję tablicy przez wartość z pliku otrzymując w pewnym przybliżeniu prawdziwe dane. Im podzielnik jest większy, tym dokładność odtwarzanych wartości jest mniejsza, jednak mniejszy wynik kwantyzacji pociąga za sobą zmniejszenie wynikowego pliku JPEG. Wybierając odpowiedni zestaw podzielników w trakcie zapisywania aplikacja ma możliwość sterowania pomiędzy wielkością pliku, a jakością obrazu.

Ostatni etap to pobranie rezultatów kwantyzacji, a następnie pobranie ich do jednego pliku. Etap ten nazywany jest kodowaniem entropii. Do najpopularniejszych rodzajów kodowania należy kodowanie Hoffmana o zmiennej długości wraz z charakterystycznym w przypadku RLE kodowaniem ciągów samych zer. Kwantowanie wysokich częstotliwości jest często równoznaczne z ich wyzerowaniem. Alternatywę dla kodowania Hoffmana stanowi kodowanie arytmetyczne. Jest ono bardziej złożone, ale trochę bardziej zmniejsza wynikowy rozmiar pliku niż kod Hoffmana. Sposób kodowania arytmetycznego stanowi własność firmy IBM oraz kilku innych koncernów, co wiąże się z pewnymi niepewnościami odnośnie licencjonowania tego sposobu kodowania, dlatego też kodowanie arytmetyczne nie jest powszechnie stosowane. Najczęściej w JPEG używa się kodowania Hoffmana. Po kodowaniu Hoffmana cały proces kompresji zostaje zakończony. Dane, które zapisane są w pliku zajmują nawet kilkanaście razy mniej miejsca niż plik początkowy.

Podsumowanie

GIF i JPEG są najczęściej używanymi formatami zapisu obrazu na stronach WWW. Biorąc pod uwagę cechy specyficzne obu formatów, nadają się one najlepiej do wyszczególnionych poniżej zastosowań.

Format GIF powinien być używany w:

  • prostych obrazkach tworzących menu strony,
  • zamieszczanych na stronie animacjach ( w obecnych czasach wypierane przez animacje flash ),
  • publikacja rysunków technicznych i wszelkich obrazków o małej liczbie kolorów (zwłaszcza obrazki czarno - białe).

Format JPEG powinien być używany do:

  • publikowania zdjęć,
  • tworzenia na stronach WWW zaawansowanych grafik,
  • wszędzie tam gdzie liczba kolorów jest duża i obraz wynikowy uzyskany przy pomocy kompresji GIF nie jest zadowalający.

Dwa opisywane w tym artykule formaty kompresji obrazu stanowią światowe standardy już od kilkunastu lat i nie zanosi się na to, że zostaną kiedyś wyparte. Warto więc zapamiętać ich podstawowe cechy i podczas kompresji zdjęć i rysunków wykorzystywać je w przeznaczonym dla nich celu.