Algorytmy kodowania Shannona-Fano i Huffmana Algorytmy Kompresji Danych wykład 3 Roman Starosolski
Plan wykładu Algorytm kompresji statystycznej Algorytm Shannona-Fano Algorytm Huffmana Rozszerzone kody Huffmana Dynamiczne kodowanie Huffmana Adaptacyjny algorytm kompresji z wykorzystaniem rodziny kodów (Golomb, Golomb-Rice)
Algorytm kompresji statystycznej Algorytm kompresji statystycznej = = probabilistyczny model danych + + koder entropijny (+ dodatkowe przetwarzanie) (+ dekoder)
Koder entropijny Koder entropijny to algorytm, którego zadaniem jest, na podstawie znajomości prawdopodobieństw występowania symboli, binarne zakodowanie ciągu symboli tak, aby zminimalizować średnią długość ciągu po zakodowaniu. Z podstawowego twierdzenia Shannona o kodowaniu bezszumowym: LŚr ≥ H(S) gdzie LŚr to średnia długość słowa kodowego kodu przedrostkowego. Zatem dążymy do uzyskania średniej długości słowa kodowego możliwie bliskiej entropii (stąd nazwa „koder entropijny”). Budowa kodera entropijnego jest banalnie prosta, gdy dysponujemy kodem optymalnym dla rozkładu prawdopodobieństwa symboli źródła
Algorytmy adaptacyjne i inne algorytm (semi-)statyczny stosowany w algorytmach dwuprzebiegowych przebieg 1: analiza stałego ciągu, budowa modelu przebieg 2: kodowanie problemy: dwuprzebiegowy wymaga transmisji i modelu i zakodowanego ciągu algorytm adaptacyjny algorytm jednoprzebiegowy, on-line aktualizacja modelu każdorazowo po zakodowaniu symbolu (taki model nazywamy adaptacyjnym modelem danych) problemy przyrostowa aktualizacja modelu nie może być złożona Zero Frequency Problem
Algorytmy adaptacyjne i inne algorytm stały budowa dla całej klasy danych kodowanie przy założeniu, że dane należą do tej klasy problemy dane „nie pasujące” do założeń inne kilka (stałych) modeli przełączanych adaptacyjnie podczas kodowania podział ciągu na podciągi i zastosowanie algorytmu statycznego do każdego podciągu z osobna ...
„Podstawowe twierdzenie Shannona o kodowaniu bezszumowym” (jedna z postaci twierdzenia, wg.: Drozdek: „Wprowadzenie do kompresji danych”) Dla bezpamięciowego źródła S o entropii H(S) możliwe jest przypisanie ciągom k symboli źródła, słów kodu przedrostkowego tak, że spełnione jest H(S) ≤ Lk / k < H(S) + 1 / k asymptotycznie, możliwe jest uzyskanie średniej długości kodu (w przeliczeniu na pojedynczy symbol) równej entropii źródła optymalna długość słowa kodowego dla symbolu o prawdopodobieństwie p równa jest –log (p) (czyli autoinformacji dla tego symbolu) można zbudować koder entropijny o efektywności bliskiej 100%
Jak wygenerować kod przedrostkowy? Problem: Mamy wyznaczony przez model rozkład prawdopodobieństwa symboli źródła p1, p2, p3, p4 ... pN, : ∑pi = 1 Znamy optymalne długości słów kodowych (tj. przybliżone długości słów optymalnego kodu przedrostkowego) l1, l2, l3, l4 ... lN : li = –log (pi) Wiemy jaki warunek muszą spełniać długości słów kodowych aby istniał kod jednoznacznie dekodowalny (nierówność Krafta) ∑2-li ≤ 1 Chcemy wyznaczyć Kod przedrostkowy o minimalnej średniej długości kodu szukamy: dokładnych długości słów szukamy: postaci (kolejnych bitów) słów
Algorytm Shannona-Fano Algorytm Shannona-Fano generuje kod przedrostkowy dla zadanego rozkładu prawdopodobieństwa symboli alfabetu.
(na podstawie: A. Drozdek, Wprowadzenie do kompresji danych, WNT, Warszawa, 1999) Krok 1: Ustaw symbole alfabetu źródła w ciąg s uporządkowane zgodnie z prawdopodobieństwem ich użycia; Krok 2: AlgorytmShannonaFano(ciąg s) if s zawiera dwa symbole dołącz 0 do słowa kodowego jednego z symboli, 1 do słowa drugiego symbolu; elseif s zawiera więcej niż dwa symbole podziel s na dwa podciągi s1 i s2 tak, by różnica między sumą prawdopodobieństw symboli w podciągach była najmniejsza; dołącz 0 do słów kodowych symboli w s1 i 1 do słów symboli w s2; AlgorytmShannonaFano(s1); AlgorytmShannonaFano(s2); endif;
Przykład: kodujemy ciąg abracadabra w tabeli mamy ciąg symboli alfabetu źródła i kolejne kroki budowania słów kodowych ciąg s c d r b a częstość symbolu 1/11 2/11 5/11 ciąg s1 i s2 słowo symbolu 1 ciąg s11 i s12 0 0 0 1 ciąg s111 i s112 0 0 0 0 0 1 ciąg s121 i s122 0 1 0 0 1 1 wynik
Przykład: kodujemy ciąg abracadabra można wygenerować kod o innych długościach słów ciąg s c d r b a częstość symbolu 1/11 2/11 5/11 ciąg s1 i s2 słowo symbolu 1 ciąg s11 i s12 0 0 0 1 ciąg s111 i s112 0 0 0 0 0 1 ciąg s1111 i s1112 0 0 0 0 0 0 0 1 wynik
Algorytm Huffmana Algorytm Huffmana generuje kod przedrostkowy dla zadanego rozkładu prawdopodobieństwa symboli alfabetu.
W algorytmie Huffmana buduje się drzewo binarne, zwane drzewem Huffmana. Każdemu z liści odpowiada pojedynczy symbol alfabetu źródła. Z każdym węzłem skojarzona jest waga równa łącznemu prawdopodobieństwu liści w poddrzewie dla którego ten węzeł jest korzeniem Utwórz n drzew, gdzie n jest rozmiarem alfabetu źródła. Każdemu z symboli alfabetu źródła odpowiada pojedyncze drzewo składające się wyłącznie z korzenia i mające wagę równą prawdopodobieństwu wystąpienia danego symbolu. Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). Słowo kodowe kodu Huffmana dla danego symbolu znajduje się przechodząc ścieżką od korzenia drzewa Huffmana do liścia odpowiadającego temu symbolowi (i-ty bit słowa kodowego ma wartość 0, jeżeli i-ta krawędź ścieżki prowadzi do lewego syna i-tego węzła, a 1 — jeżeli do prawego).
Przykład: kodujemy ciąg abracadabra Utwórz n drzew, gdzie n jest rozmiarem alfabetu źródła. Każdemu z symboli alfabetu źródła odpowiada pojedyncze drzewo składające się wyłącznie z korzenia i mające wagę równą prawdopodobieństwu wystąpienia danego symbolu. a 5/11 b 2/11 c 1/11 d 1/11 r 2/11
Przykład: kodujemy ciąg abracadabra Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 2/11 1 a 5/11 b 2/11 c 1/11 d 1/11 r 2/11
Przykład: kodujemy ciąg abracadabra Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 4/11 1 2/11 1 a 5/11 b 2/11 c 1/11 d 1/11 r 2/11
Przykład: kodujemy ciąg abracadabra Wyznacz dwa drzewa o najmniejszych wagach i utwórz z nich nowe drzewo, w którym dwa właśnie wyznaczone drzewa te są synami korzenia o wadze równej sumie ich wag. Powtarzaj krok 2 aż pozostanie tylko jedno drzewo (n – 1 razy). 6/11 1 4/11 1 2/11 1 a 5/11 b 2/11 c 1/11 d 1/11 r 2/11
Przykład: kodujemy ciąg abracadabra 1 1 6/11 1 4/11 1 2/11 1 a 5/11 b 2/11 c 1/11 d 1/11 r 2/11
Przykład: kodujemy ciąg abracadabra Słowo kodowe kodu Huffmana dla danego symbolu znajduje się przechodząc ścieżką od korzenia drzewa Huffmana do liścia odpowiadającego temu symbolowi (i-ty bit słowa kodowego ma wartość 0, jeżeli i-ta krawędź ścieżki prowadzi do lewego syna i-tego węzła, a 1 — jeżeli do prawego). r 2/11 d 1/11 c a 5/11 b 4/11 6/11 1 symbol słowo kodowe a b 1 0 0 c 1 0 1 0 d 1 0 1 1 r 1 1
Własności kodów Huffmana Podobnie, jak algorytm Shannona-Fano, przedstawiony algorytm jest niedeterministyczny niedeterminizm można łatwo usunąć – kanoniczne kodowanie Huffmana Efektywnośc kodów Huffmana jest typowo nieznacznie większa niż Shannona-Fano (dla przykładu „abracadabra” jest taka sama) algorytm Huffmana jest prostszy symbol Shannon-Fano (1) Shannon-Fano (2) Huffman a 1 b 0 1 1 0 1 1 0 0 c 0 0 0 0 0 0 0 1 0 1 0 d 0 0 1 0 0 0 1 1 0 1 1 r 0 1 0 1 1
Własności kodów Huffmana Kod wygenerowany algorytmem Huffmana jest optymalny w klasie kodów przedrostkowych (gdy prawdopodobieństwa symboli są 2 -N, gdzie N jest nieujemną liczbą całkowitą, to kod jest optymalny, gdyż dla symbolu o prawdopodobieństwie p optymalna długość słowa kodowego to –log (p) bitów) Nieefektywność kodu Huffmana Jednocześnie nieefektywność kodów przedrostkowych pmax to prawdopodobieństwo najbardziej prawdopodobnego symbolu.
Rozszerzone kody Huffmana Kod Huffmana jest nieefektywny, gdy prawdopodobieństwo wystąpienia jednego z symboli jest duże, najbardziej gdy bliskie 1. długość słowa kodowego tego symbolu wynosi 1 bit optymalna długość słowa kodowego jest bliska 0 zatem średnia długość kodu jest wielokrotnie większa od entropii rozkładu prawdopodobieństwa symboli.
„Podstawowe twierdzenie Shannona o kodowaniu bezszumowym” (jedna z postaci twierdzenia, wg.: Drozdek: „Wprowadzenie do kompresji danych”) Dla bezpamięciowego źródła S o entropii H(S) możliwe jest przypisanie ciągom k symboli źródła, słów kodu przedrostkowego tak, że spełnione jest H(S) ≤ Lk / k < H(S) + 1 / k asymptotycznie, możliwe jest uzyskanie średniej długości kodu (w przeliczeniu na pojedynczy symbol) równej entropii źródła optymalna długość słowa kodowego dla symbolu o prawdopodobieństwie p równa jest –log (p) (czyli autoinformacji dla tego symbolu) można zbudować koder entropijny o efektywności bliskiej 100%
Rozszerzone kody Huffmana Kod Huffmana jest nieefektywny, gdy prawdopodobieństwo wystąpienia jednego z symboli jest duże, najbardziej gdy bliskie 1. długość słowa kodowego tego symbolu wynosi 1 bit optymalna długość słowa kodowego jest bliska 0 zatem średnia długość kodu jest wielokrotnie większa od entropii rozkładu prawdopodobieństwa symboli. Zamiast konstruować kod dla symboli alfabetu źródła możemy zinterpretować kodowany ciąg jako ciąg nad rozszerzonym alfabetem zawierającym ciągi symboli alfabetu źródła
EHuffBin=( H(S)/LHuffBin )•100%=47% Przykład: Rozszerzone kody Huffmana Kodujemy ciąg binarny (alfabet źródła to {0, 1}) Prawdopodobieństwo wygenerowania zera przez źródło wynosi 0.9 Entropia rozkładu prawdopodobieństwa H(S) wynosi 0.467. Efektywność kodu Huffmana dla tego źródła wynosi EHuffBin=( H(S)/LHuffBin )•100%=47% Jeżeli kodować będziemy pary symboli ... ... to średnia długość słowa kodowego (w przeliczeniu na symbol alfabetu źródła) wyniesie 0.649, czyli efektywność kodu wzrośnie do około 72 %. ciąg p(ciąg) słowo kodowe 00 0.81 01 0.09 10 110 11 0.01 111
Algorytm kompresji z kodowaniem Huffmana Typowe zastosowanie algorytmu Huffmana (i Shannona-Fano) to statyczny algorytm kompresji. zbudowanie modelu wymaga znajomości rozkładu prawdopodobieństwa symboli źródła, praktycznie przesyła się tablicę częstości wystąpień symboli koszt transmisji modelu np. dla alfabetu źródła ASCII jest niewielki kodowanie jest bardzo szybkie po zbudowaniu modelu wyliczamy słowa kodowe wszystkich symboli alfabetu źródła kodowanie polega na wyprowadzeniu już wyliczonych słów kodowych dla kolejnych symboli kodowanego ciąg
Algorytm kompresji z kodowaniem Huffmana Zalety prosty szybki wady nieefektywny gdy prawdopodobieństwo wystąpienia jednego z symboli alfabetu źródła jest duże (ale można kodować ciągi symboli) dwuprzebiegowy koszt transmisji modelu może być duży nie do zastosowania wprost do kodowania on-line
Dynamiczne kodowanie Huffmana Użycie algorytmu Huffmana w adaptacyjnym modelu jest możliwe Metoda brute-force – każdorazowo po zakodowniu symbolu buduj od nowa drzewo Huffmana ( Uwaga na Zero Frequency Problem ) ... ale w praktyce zbyt kosztowne
Dynamiczne kodowanie Huffmana Algorytmy Dynamicznego kodowania Huffmana (Adaptacyjne kodowanie Huffmana) To algorytm generujący kod zbliżony do kodu Huffmana, nadający się do zastosowania w algorytmie adaptacyjnym Drzewo Huffmana budowane jest przyrostowo – możliwa jest „aktualizacja modelu” Ww. algorytm został wynaleziony niezależnie przez Fallera i Gallagera ... udoskonalony przez Cormacka i Horspoola oraz (niezależnie) przez Knutha ... następnie udoskonalony przez Vittera
Algorytm Fallera-Gallagera Budujemy przyrostowo drzewo binarne, którego węzły zawierają liczniki częstości, a liście są dodatkowo skojarzone z symbolami alfabetu źródła Drzewo ma własność rodzeństwa gdy: każdy węzeł nie będący liściem ma 2 potomków przechodząc węzły w kolejności z góry do dołu, a na danym poziomie od prawej do lewej, otrzymamy ciąg węzłów o nierosnących licznikach Drzewo mające własność rodzeństwa jest drzewem Huffmana (tw. Fallera-Gallagera)
Przykład: drzewo mające własność rodzeństwa (wygląda znajomo?) 11 a 5 6 r 2 4 b 2 2 c 1 d 1
Algorytm Fallera-Gallagera Budowane drzewo zawiera liść (0-węzeł) reprezentujący wszystkie symbole, które jeszcze nie wystąpiły w kodowanym ciągu Kodowanie rozpoczynamy od drzewa składającego się wyłącznie z 0-węzła Używamy pomocniczej struktury węzły, listy dwukierunkowej zawierającej węzły drzewa uporządkowane w kolejności przeglądania drzewa z góry do dołu, a na danym poziomie od prawej do lewej Podlistę listy węzły składającą się z wszystkich węzłów o wartości licznika i nazywamy blokiem-i , a pierwszy węzeł takiego bloku liderem
(na podstawie: A. Drozdek, Wprowadzenie do kompresji danych, WNT, Warszawa, 1999) DynamiczneKodowanieHuffmanaFGK(symbol s) p = liść zawierający symbol s; wyprowadź słowo kodowe dla s (*); if p jest 0-węzłem utwórz nowy węzeł q dla symolu s; q.licznik = 1; p = nowy węzeł w miejscu 0-węzła będący rodzicem 0-węzła i węzła q; p.licznik = 1; else p.licznik++; endif while p nie jest korzeniem if p narusza własność rodzeństwa if lider bloku-i zawierającego p nie jest rodzicem p zamień p z liderem; p = rodzic(p); endwhile
Przykład: kodujemy ciąg abrr, inicjalizacja i wstawienie pierwszego symbolu ( a ) 1 a q
Przykład: kodujemy ciąg abrr, wstawienie symbolu b 1 a 1 a b p q q
Przykład: kodujemy ciąg abrr, wstawienie symbolu b 1 a 1 a b 2 a 1 b p q q
wstawienie symbolu r r 2 a 1 b
wstawienie symbolu r r 2 a 1 b 1 r p 2 a b
wstawienie symbolu r (przywróć własność rodzeństwa) 2 a 1 b 1 r p 2 a b 1 r p 2 a b
wstawienie symbolu r (przywróć własność rodzeństwa) 1 r p 2 a b
wstawienie symbolu r (przywróć własność rodzeństwa) 1 r p 2 a b 2 p a 1 1 r 2 b
wstawienie symbolu r r 1 r p 2 a b 2 3 p a 1 a 1 1 r 2 b 1 r 2 b
ponowne wstawienie symbolu r (ciąg abrr) 3 a 1 1 r 2 b
ponowne wstawienie symbolu r (ciąg abrr) 3 3 a 1 1 r 2 b a 1 1 r 2 b p
ponowne wstawienie symbolu r (przywróć własność rodzeństwa) 3 3 3 a 1 1 r 2 b a 1 1 r 2 b a 1 1 r 2 b p p
ponowne wstawienie symbolu r (przywróć własność rodzeństwa) 3 a 1 r 2 b p
ponowne wstawienie symbolu r (przywróć własność rodzeństwa) 3 a 1 r 2 b p 4 r 2 1 a b p
postać drzewa po przetworzeniu ciągu abrr 4 r 2 1 a b
Algorytm Vittera Dodatkowe założenie: w bloku-i węzłów najpierw znajdują się węzły wewnętrzne, później liście minimalizujemy głębokość drzewa bardziej złożone staje się przywracanie własności rodzeństwa ciąg o długości s zakodujemy na nie więcej niż h+s bitach, gdzie h to liczba bitów dla kodowania statycznego Huffmana ten algorytm radzi sobie z ZFP lepiej, niż algorytm Fallera-Gallagera (dla niektórych ciągów wynik dynamicznego kodowania Huffmana może by lepszy, niż w statycznym algorytmie, bo tu nie przesyłamy modelu)
Adaptacyjny algorytm kompresji z wykorzystaniem rodziny kodów (Golomb, Golomb-Rice) Algorytm adaptacyjny można zbudować z kilku stałych modeli Ale po kolei ... Zmodyfikowane kody binarne Rodzina kodów Golomba Rodzina kodów Golomba-Rice’a Model danych dla parametrycznej rodziny kodów (model algorytmu FELICS)
Zmodyfikowany kod binarny prefiksowy kod dla skończonego alfabetu, np. dla liczb 0 .. j-1 słowa kodowe o długości log(j) lub log (j) bitów, gdzie j to rozmiar alfabetu właściwie to rodzina kodów (długość słowa kodowego kodu binarnego dla alfabe- tu j symboli to log(j) ) Symbol Alfabet 0 .. 4 0 .. 5 0 .. 6 0 .. 7 . 0 0 . 0 0 0 1 . 0 1 . 0 1 0 . 0 0 1 2 . 1 0 . 1 0 0 . 0 1 1 3 . 1 1 0 . 1 0 1 4 . 1 1 1 5 6 7
Zmodyfikowany kod binarny Generowanie słowa kodowego kodujemy liczbę i zmodyfikowanym kodem binarnym dla liczb 0 .. j – 1, przyjmijmy N = log(j) i n = 2 N jeżeli i < n – j zakoduj i za pomocą N – 1 -bitowego kodu binarnego else zakoduj i + n – j za pomocą N -bitowego kodu binarnego Własności zmodyfikowanego kodu binarnego długość słowa kodowego: log(j) lub log (j) dla j = 2 N kod staje się N -bitowym kodem binarnym liczba dłuższych słów kodowych jest zawsze parzysta
Kod Golomba Kody Golomba parametryczna rodzina kodów przeznaczona do kodowania nieujemnych liczb całkowitych nieskończona parametrem kodu jest całkowite m, m > 0 zawiera kody optymalne dla wykładniczego rozkładu prawdopodobieństwa symboli (dla niektórych parametrów rozkładu) (nadaje się do źródeł o rozkładzie nierosnącym) słowa kodowe łatwe w generacji i dekodowaniu
Kod Golomba
Kod Golomba Generowanie słowa kodowego kodujemy liczbę x kodem Golomba z parametrem m prefiks słowa: x/m zakodowane unarnie (kod α Eliasa) sufiks: x mod m zakodowane zmodyfikowanym kodem binarnym dla przedziału [0, m – 1]
Kod Golomba Generowanie słowa kodowego kodujemy liczbę x kodem Golomba z parametrem m np. 8 kodem Golomba z parametrem 3 prefiks słowa: x/m zakodowane unarnie (kod α Eliasa) 8/3 = 2 110 sufiks: x mod m zakodowane zmodyfikowanym kodem binarnym dla przedziału [0, m – 1] 8 mod 3 = 2 11
Kod Golomba
Kod Golomba-Rice’a Jest to szczególny przypadek kodu Golomba zauważony już przez Golomba i niezależnie od niego odkryty przez Rice’a: Kody Golomba są szczególnie proste, gdy m = 2 k kodujemy liczbę x kodem Golomba-Rice’a z parametrem k prefiks słowa: x/ 2 k zakodowane unarnie (kod α Eliasa) x >> k sufiks: x mod 2 k zakodowane zmodyfikowanym kodem binarnym dla przedziału [0, m – 1] k najmniej znaczących bitów x
Kody Golomba i Golomba-Rice’a Dla skończonego alfabetu używamy tylko części nieskończonej rodziny przyjmijmy rozmiar alfabetu 2 N dla rodziny Golomba kody o m > 2 N-1 mają słowa kodowe wszystkich symboli alfabetu dłuższe od kodu o m = 2 N-1 sensowne jest używanie początkowych 2 N-1 kodów dla kodów Golomba-Rice’a kody o k > N – 1 mają słowa wszystkich symboli alfabetu dłuższe od kodu o k = N – 1 sensowne jest używanie początkowych N kodów (k = 0 .. N – 1 )
Kody Golomba i Golomba-Rice’a
Model danych dla parametrycznej rodziny kodów Rodziny Golomba-Rice’a można użyć do kodowania ciągów symboli o wykładniczym rozkładzie prawdopodobieństwa. (rozkład często spotykany w kompresji obrazów, dźwięków ... ) Jeżeli parametr rozkładu jest nieznany, lub zmienia się w trakcie pracy źródła to parametr kodu Golomba-Rice’a trzeba dobierać adaptacyjnie Jak to zrobić ?
Model danych dla parametrycznej rodziny kodów Jak to zrobić ? to proste ... Wybierajmy ten kod, który jest najlepszy dla już przetworzonych symboli Jak to zrobić?
Model algorytmu FELICS dla parametrycznej rodziny kodów Algorytm modelowania zastosowany przez Howarda i Vittera w algorytmie bezstratnej kompresji obrazów FELICS dla każdego kodu z rodziny utrzymuj licznik (tablica liczników) licznik liczby bitów, którą uzyskano by kodując dotychczas przetworzoną część ciągu tym kodem po zakodowaniu symbolu zwiększ licznik każdego z kodów o długość słowa kodowego właśnie zakodowanego symbolu w kodzie odpowiadającym licznikowi do kodowania symbolu użyj kodu o najmniejszym liczniku
Model algorytmu FELICS dla parametrycznej rodziny kodów udoskonalenie: okresowo, gdy wartość najmniejszego z liczników przekroczy pewien próg, podziel wszystkie liczniki przez 2 unikniemy przepełnienia zwiększymy znaczenie symboli kodowanych niedawno ww. metoda to tylko część całego algorytmu (i tylko część modelu) metoda z FELICS nadaje się do każdej rodziny jeszcze prostsza metoda istnieje dla rodziny Golomba-Rice’a Zastosowana przez Weinberger, Seroussi, Sapiro w algorytmie LOCO(JPEG-LS) Niezależnie od rozmiaru alfabetu mamy 2 liczniki (licznik zakodowanych symboli i licznik sumy wartości tych symboli)