kodowanie słownikowe

Transkrypt

kodowanie słownikowe
Algorytmy kodowania
słownikowego
•
•
Kodowanie ze słownikiem dynamicznym
(LZ77, LZ78, LZSS, LZW)
Zastosowania
Kodowanie słownikowe - zasada
Chcemy zakodować zdanie angielskie:
A good example of how dictionary based compression works
Słownik: Longman Dictionary of Contemporary English
Kodowanie: wskaźnik do słowa to x/y, x – nr strony, y – nr
słowa na stronie. Wynik:
1/1 489/7 377/19 755/36 548/13 303/7 73/3 223/1 1270/25
Liczba stron w słowniku: 1280 – x kodujemy przez 11 bitów
Liczba słów na stronie < 128 – y kodujemy przez 7 bitów
Wskaźnik x/y – 18 bitów. Całkowita ilość bitów: 9*18 = 162
Normalne kodowanie ASCII – 48 bajtów, czyli 384 bity
Stopień kompresji – 2.37 : 1
Słownik dynamiczny
Największe znaczenie – metody ze słownikiem
dynamicznym
Przełomowe znaczenie – prace Jacoba Ziva i Abrahama
Lempela z końca lat siedemdziesiątych
Słownik budowany dynamicznie na podstawie
przetworzonej części danych – równy fragmentowi
przetworzonej części danych lub wytworzony ze
wszystkich fraz przetworzonych do tej pory
NajwaŜniejsze algorytmy: LZ77, LZ78, LZW
Algorytm LZ77
Słownik – fragment wcześniej zakodowanej części danych
Przeglądamy dane przez przesuwające się okno o
rozmiarze W
Okno dzieli się na:
bufor słownikowy – zawiera ostatnio zakodowany fragment ciągu
danych
bufor kodowania – zawiera fragment ciągu, który właśnie mamy
kodować
Praktyczne implementacje – rozmiar bufora
słownikowego: 8 – 16 kB, rozmiar bufora kodowania ~
100 bajtów
Algorytm LZ77 – c.d.
Zasada działania:
Umieszczamy wskaźnik przeszukiwania na końcu bufora
słownikowego
Przesuwamy wskaźnik w lewo (liczba miejsc – o) aŜ do
napotkania symbolu równego pierwszemu symbolowi w buforze
kodowania
Sprawdzamy, czy następne symbole w obu buforach nie są sobie
równe. Liczba równych sobie symboli – długość dopasowania l
Przeglądamy w ten sposób cały bufor słownikowy tak, by
zmaksymalizować dopasowanie
Optymalne dopasowanie kodujemy jako (o, l, c), gdzie c – kod
symbolu w buforze kodowania występujący jako pierwszy
niedopasowany symbol
k a b
r
a k a d a
7
b
r
4
a
r
r
a
(7, 4, C(r))
Algorytm LZ77 – c.d.
Ostatni element trójki – na wypadek zerowego dopasowania
Po wysłaniu kodu (o, l , c) przesuwamy okno o l + 1 w prawo i
powtarzamy procedurę
Długość zapisu kodującego dla kodowania o stałej
długości
niech rozmiar okna = W, rozmiar bufora słownikowego = S,
rozmiar alfabetu = A
wtedy długość zapisu = log2 S + log2 W + log2 A
Uwaga: dopasowanie moŜe przekroczyć rozmiar bufora
słownikowego
Algorytm LZ77 – kodowanie
Kodujemy ciąg:
. k a b r a k a d a b r a r r a r r a d .
Zakładamy, Ŝe podciąg k a b r a k a jest juŜ zakodowany.
Parametry okna: W=13, S=7
Kolejne kroki kodowania:
k
a
b
r
a
k
a
d
a
b
r
a
r
(0,0,C(d))
a
b
r
a
k
a
d
a
b
r
a
r
r
(7,4,C(r))
a
d
a
b
r
a
r
r
a
r
r
a
d
(3,5,C(d))
Algorytm LZ77 – dekodowanie
Startujemy z odkodowanego podciągu k a b r a k a
Odkodowujemy (0,0,C(d)) – czyli C(d)
k a b
r
a k a
d
Kopiowanie 1 znaku
Odkodowujemy (7,4,C(r))
k a b
r
a k a d
k a b
r
a k a d a
Przesunięcie o 7
Kopiowanie 2 znaku
k a b
r
Kopiowanie 3 znaku
a k a d a b
k a b
r
r
a k a d a b
r
r
Odkodowanie C(r)
Kopiowanie 4 znaku
k a b
a k a d a b
a
k a b
r
a k a d a b
r
a
r
Algorytm LZ77 – dekodowanie – c.d.
Odkodowanie (3,5,C(d))
a b a b
r
a
r
1 znak
a b a b
r
a
r
o 3 pozycje
2 znak
a b a b
r
a
r r
r
3 znak
a b a b
a
r
a
r r
a
r
4 znak
a b a b
r
a
r r
a
r
5 znak
a b a b
r
Odkodowanie C(d)
a b a b
r
a
r r
a
r
r
a
d
r
a
r r
a
r
r
a
Algorytm LZ77 – własności
Prosta metoda adaptacyjna, nie wymaga wcześniejszej
wiedzy o charakterze źródła
Kodowanie moŜe być czasochłonne (duŜo porównań);
dekodowanie proste i szybkie
NieduŜe wymagania dotyczące pamięci
Asymptotycznie – wyniki najlepsze jakie moŜna uzyskać
przy pełnej częstości pojawiania się znaków i korelacji
między nimi
MoŜna zastosować róŜne modyfikacje algorytmu
poprawiające jego efektywność
Odmiany LZ77
Algorytm LZSS – unika konieczności wysyłania (o,l,c)
Redundancja – albo nie trzeba pointera (bo jest zerowy), albo kodu
znaku (moŜe być przekazany w następnym wejściu)
Działanie:
• Znajdź dopasowanie (o,l)
• JeŜeli l ≥ MIN_LENGTH to wysyłamy (o, l ) i przesuwamy okno o l
• JeŜeli l < MIN_LENGTH to wysyłamy kod pierwszego znaku z
bufora kodowania i przesuwamy okno o 1
• Aby rozróŜnić oba przypadki ich zapisy poprzedzamy odpowiednimi
flagami bitowymi
Inne modyfikacje – poprawa efektywności kodowania –
kodowanie trójek (lub dwójek liczb) kodowaniem o
zmiennej długości – pakiety Pkzip, Zip, gzip, ARJ, LHarc
Zastosowanie efektywnych struktur danych do
reprezentacji zawartości bufora słownikowego (TRIE)
Algorytm LZ78
Wada algorytmu LZ77 – skończony czas, w jakim wzorzec
jest pamiętany – wzorce odległe o bardziej niŜ szerokość
bufora słownikowego nie „czują” swej obecności
a b c d e f g h i a b c d e f g h i a b c d e f g i a b
LZ78 – zastąpienie bufora słownikowego słownikiem
tworzonym explicite – dynamicznie w trakcie kodowania i
dekodowania
Słowniki – tabela zawierająca indeks i odpowiadający mu
wzorzec. Na początku kodowania (dekodowania) – słownik
pusty. Potem – ostatnio dopasowany wzorze + niedopas. znak
Kodowanie – para (i,c), gdzie i – indeks, c – kod pierwszego
niedopasowanego znaku
LZ78 – przykład
Ciąg do zakodowania: aa_bbb_cccc_ddddd_e
Słownik:
Nr
Wzorzec
0
^
1
a
2
a_
3
b
4
bb
5
_
6
c
7
cc
8
c_
9
d
10
dd
11
dd_
12
e
Kodowanie:
(0,a)(1,_)(0,b)(3,b)(0,_)(0,c)
(6,c)(6,_)(0,d)(9,d)(10,_)
(0,e)
Do słownika wstawiane są
coraz dłuŜsze wzorce. JeŜeli
jakaś fraza się powtarza, to
wkrótce znajdzie się w
całości w słowniku.
Odkodowanie – bardzo
proste.
Własności algorytmu LZ78
Szybsze kodowanie niŜ dla LZ77 (znacznie mniej
porównań stringów)
Łatwe dekodowanie (choć wolniejsze niŜ dla LZ77 –
konieczność odbudowy słownika)
Wzorce są stale dodawane do słownika (1 wzorzec na
jeden proces kodowania) i nie zapominane –
niebezpieczeństwo przepełnienia pamięci
Jest punktem wyjścia dla algorytmów pochodnych –
najbardziej znany algorytm LZW.
Algorytm LZW
Zaproponowany w 1984 przez Terry’ego Welcha
Główna modyfikacja – koder nie wysyła kodu pierwszego
niedopasowanego znaku (a tylko indeks słownika)
Aby to było moŜliwe – słownik na starcie zawiera
wszystkie litery wyjściowego alfabetu
Procedura kodowania:
Próbujemy dopasować kawałek łańcucha wejściowego
Niech s – maksymalny podłańcuch który ma wzorzec w słowniku
(indeks j) o długości d, c – pierwszy niedopasowany znak
Na wyjście: j (indeks wzorca zgodnego z s)
Do słownika dodajemy s+c
Przesuwamy znacznik pozycji o d
Algorytm LZW – kodowanie
• Przykład: kodujemy ciąg a b c a b b c a b b a
a w D, ab – nie, ab do D4, wyjście 1
Indeks
Wzorzec
1
a
b w D, bc – nie, bc do D5, wyjście 2
2
b
c w D, ca – nie, ca do D6, wyjście 3
3
c
ab w D, abb – nie, abb do D7, wyjście 4
4
ab
bc w D, bca – nie, bca do D8, wyjście 5
5
bc
abb w D, abba – nie, abba do D9, wyjście 7
6
ca
7
abb
8
bca
9
abba
a w D, wyjście 1
Wynik:
1234571
Zastosowanie LZW
Format GIF
Podstawa – b = ilość bitów na piksel.
Zaczynamy od słownika o rozmiarze 2b+1. Po
wypełnieniu – zwiększamy o czynnik 2.
Maksymalny rozmiar – 4096. Po jego osiągnięciu –
słownik jest zamroŜony.
Kompresja obrazów - zestawienie
Huffman
Obraz
Huffman Dyn. Huff.
róŜnice
róŜnice
GIF
1_ch
57 504
32 968
32 261
51 085
2_ch
61 430
38 541
37 896
60 649
Ziemia
40 543
33 880
39 501
34 276
Miasto
58 374
52 643
52 321
61 580