Kompresja JPEG

Stratna kompresja oparta na DCT dla obrazów fotograficznych z kontrolą jakości.

Problem Fotografii Cyfrowej: Dlaczego Potrzebujemy JPEG

W erze smartfonów i aparatów o wysokiej rozdzielczości, fotografie cyfrowe traktujemy jako coś oczywistego. Robimy zdjęcia, natychmiast je udostępniamy i przechowujemy ich tysiące na naszych urządzeniach. Jednak za każdym ostrym, żywym zdjęciem kryje się ogromna ilość surowych danych. Pojedyncza, nieskompresowana, wysokiej jakości fotografia z nowoczesnego aparatu może z łatwością przekroczyć 20 do 30 megabajtów. Przechowywanie albumu wakacyjnego składającego się z kilkuset zdjęć pochłonęłoby gigabajty przestrzeni, a próba wysłania nawet jednego z tych plików e-mailem byłaby powolnym i frustrującym doświadczeniem.

Ta ciężka pod względem danych natura obrazów cyfrowych stanowiła znaczącą barierę dla rozwoju fotografii cyfrowej i internetu. Rozwiązaniem, które się pojawiło i stało niekwestionowanym światowym standardem, jest JPEG. to nie tylko format pliku; to zaawansowana metoda zaprojektowana specjalnie dla obrazów o ciągłych tonach, takich jak fotografie. Jej geniusz polega na zdolności do radykalnego zmniejszania rozmiarów plików, często o współczynnik 10 lub więcej, przy jednoczesnym utrzymaniu widocznej utraty jakości na absolutnym minimum. Osiąga to, sprytnie wykorzystując znane ograniczenia i charakterystykę ludzkiego systemu wzrokowego.

Potok Kompresji JPEG: Podróż Krok po Kroku

Proces kompresji JPEG najlepiej jest rozumieć jako wieloetapowy potok, w którym dane obrazu są stopniowo przekształcane, redukowane i pakowane. Każdy krok odgrywa kluczową rolę w ostatecznym współczynniku kompresji i jakości. Prześledźmy podróż obrazu, gdy jest on kompresowany do pliku JPEG.

Krok 1: Transformacja Przestrzeni Kolorów

Większość obrazów cyfrowych jest przechwytywana i początkowo przechowywana w przestrzeni kolorów RGB (Czerwony, Zielony, Niebieski), gdzie kolor każdego piksela jest definiowany przez intensywność tych trzech podstawowych kolorów. Chociaż jest to intuicyjne dla wyświetlaczy, nie jest idealne dla kompresji. Pierwszym krokiem w procesie JPEG jest konwersja obrazu z RGB na inną przestrzeń kolorów, zazwyczaj YCbCr.

Ta nowa przestrzeń dzieli informacje o obrazie na trzy składniki:

  • Y (Luminancja): Ten składnik reprezentuje informacje o jasności lub skali szarości obrazu. To jest to, co byś zobaczył, patrząc na czarno-białą wersję fotografii.
  • Cb (Chrominancja-niebieska): Ten składnik reprezentuje różnicę kolorów niebieski-żółty.
  • Cr (Chrominancja-czerwona): Ten składnik reprezentuje różnicę kolorów czerwony-zielony.

Dlaczego to robimy? To rozdzielenie jest kluczowe, ponieważ ludzki system wzrokowy jest znacznie bardziej wrażliwy na zmiany jasności (lumy) niż na subtelne zmiany koloru (chromy). Potrafimy postrzegać drobne szczegóły w skali szarości z dużą dokładnością, ale nasza percepcja koloru jest znacznie mniej precyzyjna. Izolując jasność od koloru, algorytm JPEG może traktować je inaczej w kolejnych krokach, co jest kluczowym aspektem jego podejścia psychowizualnego.

Krok 2: Podpróbkowanie Chrominancji (Downsampling)

Teraz, gdy informacja o kolorze jest oddzielona od jasności, algorytm wykorzystuje słabość naszego systemu wzrokowego. to proces zmniejszania rozdzielczości kanałów koloru (Cb i Cr). W istocie, zamiast przechowywać unikalną wartość koloru dla każdego pojedynczego piksela, algorytm przechowuje jedną wartość koloru, która jest współdzielona przez mały blok pikseli.

Jest to często opisywane za pomocą trójczłonowego stosunku, takiego jak 4:4:44:4:4, 4:2:24:2:2, lub 4:2:04:2:0. Dla bloku 4 poziomych pikseli:

  • 4:4:44:4:4: Brak podpróbkowania. Każdy z 4 pikseli ma swoją odrębną wartość Y, Cb i Cr. Zachowuje to maksymalną jakość koloru.
  • 4:2:24:2:2: Podpróbkowanie poziome. Każda para dwóch poziomych pikseli dzieli tę samą wartość Cb i Cr, podczas gdy każdy ma swoją własną wartość Y. Rozdzielczość koloru jest zmniejszona o połowę w poziomie.
  • 4:2:04:2:0: Jest to najczęstszy schemat w wideo konsumenckim i JPEG. Zarówno pozioma, jak i pionowa rozdzielczość koloru jest zmniejszona o połowę. Blok 2×22 \times 2 pikseli dzieli jedną wartość Cb i Cr.

Ten krok zapewnia znaczną kompresję, zanim jeszcze zostaną zastosowane jakiekolwiek inne złożone algorytmy, a dla większości fotografii zmiana jest percepcyjnie niewidoczna. Jest to bardzo skuteczna i czysto psychowizualna sztuczka.

Krok 3: Dyskretna Transformata Kosinusowa (DCT)

To jest matematyczny rdzeń algorytmu JPEG. Po transformacji kolorów i podpróbkowaniu, każdy kanał (Y, Cb i Cr) jest dzielony na bloki pikseli 8×88 \times 8. Każdy z tych bloków jest następnie przetwarzany przez .

Zamiast reprezentować blok jako 64 wartości pikseli, DCT reprezentuje go jako 64 współczynniki częstotliwości. Można to sobie wyobrazić jako rozkładanie złożonego wzoru wizualnego na sumę prostych, standardowych wzorów (fal kosinusowych o różnych częstotliwościach). Wynikiem DCT jest kolejny blok 8×88 \times 8, ale jego wartości reprezentują teraz częstotliwości, a nie kolory pikseli:

  • Współczynnik DC: Wartość w lewym górnym rogu bloku (F(0,0)F(0,0)) to współczynnik DC (prądu stałego). Reprezentuje on średnią wartość wszystkich 64 pikseli w oryginalnym bloku, czyli jego ogólny kolor i jasność. Jest to najważniejsza informacja wizualna.
  • Współczynniki AC: Pozostałe 63 współczynniki to współczynniki AC (prądu zmiennego). Reprezentują one szczegóły, tekstury i krawędzie w bloku. Współczynniki blisko lewego górnego rogu reprezentują zmiany o niskiej częstotliwości (łagodne gradienty), podczas gdy współczynniki w prawym dolnym rogu reprezentują zmiany o wysokiej częstotliwości (drobne szczegóły i ostre krawędzie).

Kluczowym spostrzeżeniem jest to, że dla typowego bloku 8×88 \times 8z fotografii, większość "energii" wizualnej jest skoncentrowana we współczynniku DC i kilku niskoczęstotliwościowych współczynnikach AC. Wysokoczęstotliwościowe współczynniki AC są często bardzo bliskie zeru. Zadaniem DCT jest osiągnięcie tej "kompakcji energii", co umożliwia kolejny krok.

Eksplorator jakości JPEG

Przesuwaj suwak, aby zobaczyć jak mocna kwantyzacja zmniejsza plik i wprowadza znane artefakty.

Szac. współczynnik
2.40:1
Szac. rozmiar
3.13 MB
Szac. PSNR
42.4 dB
Artefakty
Lekka blokawość
Klatka testowaQ80

Symulacja zmniejsza rozdzielczość sceny, podkreśla granice bloków 8x8 i dodaje lekkie dzwonienie jak w JPEG.

Jakość vs kompresja2.40:1
Szac. współczynnikUstawienie jakości

Krzywa przedstawia szacowany współczynnik kompresji dla typowego zdjęcia 12 MP zapisanego jako JPEG.

Krok 4: Kwantyzacja: Krok Stratny

To tutaj dzieje się prawdziwa magia kompresji stratnej i gdzie informacje są trwale odrzucane. Każdy z 64 współczynników w bloku DCT jest dzielony przez odpowiednią wartość z 64-elementowej , a wynik jest zaokrąglany do najbliższej liczby całkowitej.

Ta tablica nie jest przypadkowa; została zaprojektowana z uwzględnieniem zasad psychowizualnych.

  • Wartość w lewym górnym rogu tablicy kwantyzacji (dla współczynnika DC) jest zazwyczaj mała, zachowując kluczowe informacje o średnim kolorze z dużą precyzją.
  • Wartości stają się stopniowo większe dla współczynników o wyższych częstotliwościach. Oznacza to, że drobne szczegóły (współczynniki AC o wysokiej częstotliwości) są dzielone przez duże liczby, co powoduje, że ich wynikowe wartości są zaokrąglane do zera lub bardzo małych liczb całkowitych.

Ustawienie "jakości" przy zapisywaniu pliku JPEG (np. od 1 do 100) jest w istocie współczynnikiem skalującym dla tej tablicy kwantyzacji. Wysoka jakość (np. 95) używa mniejszych liczb w tablicy, zachowując więcej szczegółów i skutkując większym plikiem. Niska jakość (np. 20) używa bardzo dużych liczb w tablicy, odrzucając wiele szczegółów i tworząc bardzo mały plik. Po tym kroku wiele z 63 współczynników AC, zwłaszcza dla wysokich częstotliwości, staje się zerami.

Krok 5: Kodowanie Entropijne: Bezstratne Porządki

Po kwantyzacji blok współczynników jest rzadką macierzą z dużą ilością zer. Ostatnim krokiem jest efektywne uporządkowanie i zakodowanie tych danych za pomocą metod bezstratnych.

  1. Skanowanie Zygzakowate: 64 skwantyzowane współczynniki są odczytywane w porządku zygzakowatym, zaczynając od współczynnika DC w lewym górnym rogu i przesuwając się w kierunku prawego dolnego rogu. Celem tego skanowania jest zgrupowanie wielu zerowych współczynników wysokoczęstotliwościowych w długie, kolejne serie.
  2. Kodowanie Długości Serii (RLE): Długie serie zer są następnie efektywnie kodowane. Zamiast pisać "0, 0, 0, 0, 0", RLE po prostu zapisuje kod, który oznacza "pięć zer".
  3. Kodowanie Huffmana: Na koniec wynikowy strumień kodów RLE i niezerowych współczynników AC, wraz z oddzielnie obsługiwanymi współczynnikami DC, jest kompresowany za pomocą kodowania Huffmana. Ten klasyczny algorytm bezstratny przypisuje krótsze kody binarne do częściej występujących wartości i dłuższe kody do rzadszych, co ostatecznie pakuje dane w strumień bitów JPEG.

Podróż Powrotna: Dekompresja JPEG

Aby wyświetlić obraz JPEG, urządzenie musi przeprowadzić cały proces kompresji w odwrotnej kolejności. Dekoder odczytuje skompresowany strumień bitów i:

  1. Dekodowanie Entropijne: Dekompresuje kody Huffmana i odtwarza dane zakodowane RLE, aby uzyskać z powrotem zygzakowatą sekwencję skwantyzowanych współczynników DCT.
  2. Dekwantyzacja: Porządkuje sekwencję z powrotem w blok 8×88 \times 8 i mnoży każdy współczynnik przez odpowiednią wartość z tej samej tablicy kwantyzacji użytej podczas kodowania. Przywraca to przybliżoną wielkość współczynników DCT, ale informacja utracona podczas zaokrąglania jest stracona na zawsze.
  3. Odwrotna Dyskretna Transformata Kosinusowa (IDCT): Stosuje odwrotną DCT do zdekwantyzowanego bloku współczynników, przekształcając dane z domeny częstotliwości z powrotem do domeny przestrzennej, co daje blok wartości pikseli 8×88 \times 8.
  4. Rekonstrukcja: Składa wszystkie bloki 8×88 \times 8, powiększa kanały kolorów, jeśli użyto podpróbkowania chrominancji, i na koniec konwertuje obraz z YCbCr z powrotem na RGB, aby można go było wyświetlić na ekranie.

Wynikiem jest obraz, który wygląda bardzo podobnie do oryginału, ale jest zbudowany z ułamka danych.