Sie sind auf Seite 1von 5

Datenkompression: Verlustfreie Verfahren: Wrterbuchbasierte Verfahren: LZ77

1
Datenkompression: Verlustfreie Verfahren:
Wrterbuchbasierte Verfahren: LZ77
zurck
5 Verlustfreie_Verfahren
5.2 Wrterbuchbasierte Verfahren
5.2.1 LZ77 - Lempel, Ziv (1977)
5.2.2 LZ78 - Lempel, Ziv (1978)
5.2.3 LZSS - Storer, Szymanski (1982)
5.2.4 LZW - Welch (1984)
5.2.5 LZPP - Pylak (2003)
5.2.6 LZFG - Fiala, Green
5.2.7 LZRW - Williams (1989-1991)
5.2.8 LZV - Vogt (1994)
5.2.9 LZMW - Miller, Wegman (1985)
5.2.10 LZC - ?
5.2.11 LZT - Tischer (1987)
5.2.12 LZJ - Jakobsson
5.2.13 LZR - Rodeh, Pratt, Even
5.2.14 LZB - Bell
5.2.15 LZH - Herd
5.2.16 LZO - Oberhumer
5.2.17 LZP/LZCB - Bloom (1996)
5.2.18 LZAP - Storer (1988)
5.2.19 LZY - Yabba
5.2.20
LZ77 - Lempel, Ziv 1977
Abraham Lempel und Jacob Ziv stellten 1977 ein einfaches und effizientes Verfahren zur Kompression von mehr
oder minder beliebigen Inhalten vor. Das Verfahren wurde in einer Arbeit vorgestellt, die unter diesen beiden Titeln
bekannt ist; mal mit, mal ohne das Wort 'sequential': "A Universal Algorithm for [sequential] Data
Compression". Die Neuerung des Verfahrens besteht darin, dass nicht mehr einzelne Zeichen mit ihren
Auftretenswahrscheinlichkeiten Entropie-codiert, sondern gezielt die Wiederholungen von Zeichenketten ausgenutzt
werden.
Der Grundgedanke des Verfahrens besteht darin, einen zuvor gesehenen Datenstrom als Wrterbuch zu verwenden.
Dieses verwendete Wrterbuch ist in seiner Gre begrenzt. Damit immer ein aktuelles Wrterbuch vorhanden ist,
wird dieses durch einen einfachen Verschiebemechanismus realisiert, weshalb dieses Verfahren oft als "Sliding
Window" bezeichnet wird. Das gleitende Fenster besteht aus zwei Teilen, einem Such-Puffer (search buffer) und
einem Vorschau-Puffer der die nchsten zu codierenden Zeichen enthlt (look-ahead buffer). blicherweise enthlt
der Such-Puffer mehrere tausend Zeichen und der Vorschau-Puffer fr die zu codierenden Daten in etwa 100
Datenkompression: Verlustfreie Verfahren: Wrterbuchbasierte Verfahren: LZ77
2
Zeichen oder auch weniger.
Als Demonstrationsbeispiel fr die LZ77 Kompression dient der folgende Zungenbrecher: "In Ulm, um Ulm, und
um Ulm herum.".
12 11 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9
leer I n U l m , u m
Suchpuffer Vorschaupuffer |+ Diese Tabelle zeigt das gleitende Fenster, in dem sich der zu komprimierende
Datenstrom von Rechts hineingeschoben wird. Die vorhandenen Daten werden durch eine Verschiebung
nach links aktualisiert. Das rote Feld markiert den Anfang des Vorschaupuffers. (Quelle: ThePacker)
Wie man spter erkennen kann, besitzt diese Form der Codierung einige exzellente Eigenschaften. Das
LZ77-Verfahren ist besonders gut geeignet, um Wiederholungscodes zu erkennen und zu komprimieren.
Codierung
Die Codierung nach dem LZ77-Verfahren erfolgt nach dem folgenden Algorithmus.
LZ77 - Algorithmus
1. Das erste Zeichen im Vorschau-Puffer (in den Beispielen (1) und (2) rot markiert) wird im Suchpuffer gesucht.
Dazu durchsucht (aufsteigender Index im Suchpuffer) man den gesamten Suchpuffer vom jngsten zum ltesten
Eintrag.
2. Findet der Codierer das erste Zeichen im Such-Puffer, versucht er zu berprfen, ob das Folgezeichen des
Vorschau-Puffers mit dem im Suchpuffer bereinstimmt. Wenn das Folgezeichen bereinstimmt, so wird dessen
Folgezeichen berprft, bis eine Lnge gefunden wurde. Der Treffer, bestehend aus Offset und Lnge,
wird gespeichert.
3. Jetzt versucht der Codierer eine bereinstimmung zu finden, die lnger ist als die bereits gefundene, indem er
ltere Eintrge des Wrterbuches zu der Suche heranzieht. Die Schritte 1 bis 3 werden so lange ausgefhrt, bis der
gesamte Suchpuffer durchsucht worden ist. Der beste Treffer (die lngste bereinstimmung) wird jeweils
gespeichert.
4. Nach der Suche wird das Resultat als 3-Tupel gespeichert, wobei im Allgemeinen nur zwei Flle eintreten
knnen.
1. Gibt es einen Treffer mit einer Lnge , so werden der Offset, die Lnge des Treffers und das
Folgesymbol (kein Treffer) zu dem folgenden geordneten Paar zusammengefasst (Offset, Lnge,
Folgesymbol).
2. Gibt es keinen solchen Treffer, so wird das folgende 3-Tupel ausgegeben (0,0,Symbol). Das auszugebende
Symbol ist das erste Symbol aus dem Vorschaupuffer.
5. Die Schritte 1 bis 5 werden so lange ausgefhrt, bis das Ende des Eingabestroms erreicht ist.
whi1e( !end_of_daa )
{
bes.index = 0,
bes.1engh = 0,
/*
* en Suchpuffer nach der 1ngsen bereinsimmung durchforsen.
*/
for(i=1 , i<1engh_of(searchpuffer) , i++)
{
}
/*
* Ausgabe des besen Treffers
Datenkompression: Verlustfreie Verfahren: Wrterbuchbasierte Verfahren: LZ77
3
*/
if( (bes.index !=0) && (bes.1engh>=2 ) )
{
oupu_ripe1( bes.index, bes.1engh, search_buffer[bes.1engh| ),
}
e1se
{
oupu_ripe1( 0,0, search_buffer[0| ),
}
}
// Que11e:TheRac'er
Beispiel
Beispiel (1) fr eine LZ77-Kompression (Quelle: ThePacker)
12 11 10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9 Ausgabe
(leer) I n _ U l m , _ u m (0,0,"I")
(leer) I n _ U l m , _ u m _ (0,0,"n")
(leer) I n _ U l m , _ u m _ U (0,0,"_")
(leer) I n _ U l m , _ u m _ U l (0,0,"U")
(leer) I n _ U l m , _ u m _ U l m (0,0,"l")
(leer) I n _ U l m , _ u m _ U l m , (0,0,"m")
(leer) I n _ U l m , _ u m _ U l m , _ (0,0,",")
(leer) I n _ U l m , _ u m _ U l m , _ u (5,1,"u")
(leer) I n _ U l m , _ u m _ U l m , _ u n d (4,1,"_")
I n _ U l m , _ u m _ U l m , _ u n d _ u (8,6,"n")
, _ u m _ U l m , _ u n d _ u m _ U l m _ h (0,0,"d")
_ u m _ U l m , u n d _ u m _ U l m _ h e (12,7,"_")
_ u n d _ u m _ U l m _ h e r u m . (leer) (0,0,"h")
u n d _ u m _ U l m _ h e r u m . (leer) (0,0,"e")
n d _ u m _ U l m _ h e r u m . (leer) (0,0,"r")
d _ u m _ U l m _ h e r u m . (leer) (10,2,".")
fertig
Erluterungen zum Beispiel 1
Das Beispiel links wird zeilenweise von oben nach unten gelesen. Jede Zeile zeigt einen Codierschritt. In der Spalte
Ausgabe befindet sich das Dreier-Tupel, das in diesem Schritt durch den Codierer ausgegeben wird. Das rote Feld
stellt das erste zu codierende Zeichen aus dem Vorschaupuffer dar. Der Vorschaupuffer wird zu Beginn mit den
ersten Buchstaben des zu codierenden Strings aufgefllt. Da der Suchpuffer zunchst noch leer ist, ist es unmglich,
eine bereinstimmung zu finden. Deshalb wird das Zeichen I direkt in die Ausgabe geschrieben, zusammen mit der
Information, dass kein Treffer gefunden werden konnte (Offset 0 und Trefferlnge 0). Genauso verhlt es sich mit
den folgenden neun Zeichen 'n', '_', 'U', 'l', 'm' und ','.
muss berarbeitet werden
Datenkompression: Verlustfreie Verfahren: Wrterbuchbasierte Verfahren: LZ77
4
Der Buchstabe 'm' ist bereits im Suchpuffer auf der linken Seite enthalten, dennoch stimmen die auf das 'm' im
Suchpuffer folgenden Symbole nicht mit dem berein, das im Vorschaupuffer auf den Buchstaben 'm' folgt. Aus
diesem Grund wurden die Zeichen einzeln codiert.
Das folgende Symbol '_' (Leerzeichen) stellt jedoch einen Treffer dar (im Beispiel grn markiert), der mit dem
Inhalt des Vorschaupuffers zu einer bestimmten Lnge bereinstimmt. Anschlieend folgt ein nicht
bereinstimmendes Symbol ein 'n' im Vorschaupuffer und ein 'm' im Suchpuffer. Das 'n' wird als Symbol
ausgegeben, zusammen mit der Information, an welcher Stelle der gefundene Treffer zu finden ist (Offset 8) mit der
Trefferlnge (7). Diese drei Informationen werden codiert ausgegeben. Wie diese Codierung im einzelnen erfolgt
soll im Anschluss an dieses Beispiel erlutert werden.
bis hier
Codierung des Ausgabestroms
Codierung eines Treffers/Nicht-Treffers
Lnge Offset Folgezeichen
4 3 2 1 12 11 10 9 8 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1
Byte 1 (8 Bit) Byte 2 (8 Bit) Byte 3 (8 Bit)
Fr die Codierung der Trefferlnge wurde ein 4 Bit langer Wert reserviert. Damit sind alle Lngenangaben zwischen
0 und 15 exakt codierbar. Lngere Treffer wurden durch Aneinanderreihung mehrerer Treffer erreicht. Wie Sie
sehen, werden Treffer und Nicht-Treffer gleichartig codiert. Sie sind nach der Codierung immer 24 Bits lang. Bei
dieser Darstellung jedoch ergibt sich ein riesiges Sparpotential, welches in vielen spter entwickelten Varianten
ausgenutzt wurde. Fr die Offsets wurden 12 Bits zur Verfgung gestellt, womit alle Werte zwischen 0 und 4095
darstellbar sind. Die beiden Werte fr Lnge und Offset knnen in einem Block aus 16 Bits zusammengefasst
werden, das entspricht 2 Bytes. Das Folgezeichen wurde stets separat dazu ausgegeben und bildete so das dritte
Byte. Pro Treffer oder Nicht-Treffer werden exakt 3 Bytes Daten ausgeben. Da der Offset 12 Bit lang ist, kann
maximal ein 4 Kilobyte (minus ein Byte) langer Puffer adressiert werden.
Effizienz des Ausgabestroms
(0,0,'X')
Lassen Sie uns nun die mglichen Codier-Flle des LZ77-Algorithmus nher beleuchten. Zum einen kann es
passieren, dass ein Zeichen noch nicht Teil des Suchpuffers ist (0,0,'X'), dann wird ein 24 Bit langer Wert
ausgegeben, um ein 8 Bit langes Zeichen zu codieren. Dieser Fall ist bezglich der Codiereffizienz nicht optimal (=
Codierverlust). Es werden 3 mal so viele Bits bentigt wie fr die ursprnglich Nachricht.
(Offset,1,'X')
Nehmen wir an, das zu codierende Zeichen befindet sich bereits im Suchpuffer, aber das nachfolgende Zeichen ist
noch nicht Teil des Suchpuffers oder es folgt nicht auf das zu codierende Zeichen. Es tritt also der Fall
(Offset,1,'X') auf, so knnen zwei Zeichen codiert werden. Das erste Zeichen wird durch die Offset und
Lngenangabe codiert. Das Folgezeichen steht an der Stelle des Literals. Es knnen also 2*8 Bit (16 Bit) mit einem
24 Bit Wert dargestellt werden. Auch dieser Fall ist bezglich der Codiereffizienz nicht hilfreich, da fr jedes zu
codierende statt 8 Bit im Mittel 12 Bit bentigt werden. Dieser Fall ist bereits besser (1,5 fach) als gar nicht
vorhandene Zeichen (3 fach), dennoch fhren sie nicht zu einem Codiergewinn (=Codierverlust). Es werden
mehr Informationen zur Darstellung bentigt, als es zu codieren gilt.
(Offset,2,'X')
Neutral bezglich der Codiereffizienz gegenber sind Treffer der Lnge 2. Es werden 24 Bit ausgegeben, wenn 3*8
Bit codiert werden sollen. (Offset,2,'X') Bis zu dieser Treffer-Lnge sind mit der LZ77-Codierung keinerlei
Codiergewinne erzielbar. Die Hoffnung bei der Codierung ist, dass die Codierverluste durch die Codiergewinne der
Datenkompression: Verlustfreie Verfahren: Wrterbuchbasierte Verfahren: LZ77
5
lngeren bereinstimmungen wettgemacht werden knnen. Weder Codiergewinn noch Codierverlust.
(Offset,3..15,'X')
Jede Codierung der Form (Offset,3..15,'X') stellt einen Codiergewinn dar, da hiermit Zeichenketten der Lnge 4
bis 16 mit durch ein 24 Bit langen Wert dargestellt werden knnen. Alle diese Zeichenketten sind durch eine
Zeichenkette der Lnge 3 codierbar.
Wenn die Codiergewinne die Codierverluste kompensieren knnen, ist die Gesamtausgabe des codierten
Datenstroms krzer als die Eingabe und stellt eine Kompression des Datenstroms dar.
Beispiel
Beispiel (2) fr eine LZ77-Kompression (RLE-Modus) (Quelle: ThePacker)
5 4 3 2 1 0 1 2 3 4 5 Ausgabe
(leer) a a a a b (0,0,a)
(leer) a a a a b (1,3,b)
Das zweite Beispiel zeigt einen ganz speziellen Sonderfall bei der Codierung nach dem LZ77-Verfahren. In diesem
Fall ist sowohl der Vorschaupuffer als auch der Suchpuffer Teil des Treffers. Das erfordert fr den Fall "Offset <
Lnge" lediglich eine modifizierte Entpackoperation, die in diesem Fall Symbol-weise entpacken muss. Beachtet
man dies nicht, so kann es zu Fehlern im decodierten Datenstrom kommen. Wie man links sehen kann, sind mit
diesem Algorithmus identische aufeinanderfolgende Zeichen codierbar. Dieses Verfahren ist auch als
Lauflngen-Codierung/Kompression (RLE - Run Length Encoding) bekannt.
Beispiel
Beispiel (3) fr eine LZ77-Kompression (Wiederhol-Modus)
10 9 8 7 6 5 4 3 2 1 0 1 2 3 4 5 6 7 8 9 10 Ausgabe
(leer) a b c a b c a b c a d (0,0,a)
(leer) a b c a b c a b c a d (0,0,b)
(leer) a b c a b c a b c a d (0,0,c)
(leer) a b c a b c a b c a d (3,7,d)
b c a b c a b c a d (leer) fertig
Das Beispiel 3 zeigt eine Modifikation des Beispiels 2, bei dem nicht nur ein einfacher RLE-Code prsentiert wird,
sondern zeigt einen Wiederholungscode, wobei sich dieser rein programmiertechnisch vom RLE-Modus nicht
unterscheidet. Es sollte lediglich eine weitere Ausprgung gezeigt werden, mit der es mglich ist, sich
wiederholende Zeichenkombinationen zu packen. Dieses Beispiel soll an der Zeichenkette "abcabcabcad"
demonstriert werden. Es wurden 4 Tripel (12 Byte) fr 11 Zeichen ausgegeben. Man kann in diesem Fall nicht von
einer effizienten Codierung sprechen.
Der gesamte Codiervorgang besteht im Grunde genommen aus zwei Teilen, aus der Codierung und aus einer
Anpassung an den zu codierenden Datenstrom. Je weniger Anpassung es gibt, desto schlechter ist die
Codiereffizienz. Am Anfang des Codierprozesses ist keine Anpassung an die zu codierenden Daten vorhanden.
Diese wird sukzessive vorgenommen. Mit weiterem Fortschritt der Codierung steigt die Wahrscheinlichkeit, einen
Treffer zu erzielen, sofern es sich nicht um vllig zufllige Daten handelt.
Aufgaben
Aufgabe(n) - LZ77-Codierung