Verlustfreie Komprimierungsverfahren
PU separatorWechsel zu LOD1.Wechsel zu LOD3
Lauflängenkodierung
Die Lauflängenkodierung (Run Length Encoding = RLE) ist ein sehr einfaches und schnelles Verfahren. In vielen Daten kommen Folgen identischer Zeichen (Bytes) vor. Diese Tatsache macht sich dieses Verfahren zu nutze und ersetzt diese im Ausgabecode durch das Zeichen gefolgt von einem Zähler, der die Anzahl des Auftretens angibt. Um den Zähler zu kennzeichnen wird ihm ein Zeichen vorangestellt, das im Originaltext selten vorkommt (es kann aber durchaus auftreten). Für das folgende Beispiel sei dies das Zeichen ‚!’.
block separator
Beispiel
Umkomprimierter Originaltext:
  • ABCCCCCCCDEEEEEEFGGG
RLE - komprimiert:
  • ABC!7DE!6FGGG
Im Beispiel gibt es eine Reduktion von 21 auf 14 Zeichen (Byte). Das entspricht einer Kompression um 33,3% (14/21 = 0,666…).

block separator
block separator
Information
Ein Zähler wird erst ab vier identischen Zeichen verwendet, da es bei drei Zeichen noch keine Ersparnis gibt. Bei einem oder zwei Zeichen wäre die Nachricht bei Verwendung eines Zählers sogar länger.

block separator
Eine Zahl im Code kann nun einerseits ein normaler Textbestandteil sein (eine Zahl eben), oder ein Zähler. Um einen Zähler anzuzeigen, wird ihm ein Fluchtzeichen (Escape-Symbol) –hier ‚!’ - vorangestellt. Die Zahlen 7 und 6 im obigen Beispiel sind Zähler für C bzw. E. Da nun ein ! bereits im Ausgangstext vorkommen kann, behilft man sich in einem solchen Fall damit, dem ! dann eine 0 folgen zu lassen. Dies ist eindeutig, da ein Zähler mit dem Wert 0 sonst nie vorkommen kann.
block separator
Beispiel
Umkomprimierter Originaltext:
  • ABCCCCCCCDEEEEEEFGGG
RLE - komprimiert:
  • ABC!7DE!6FGGG
Im Beispiel werden die Daten von 25 auf 18 Byte reduziert. Da 18/28 gleich 0,72 ist, beträgt die Ersparnis 28%.

block separator
RLE eignet sich besonders für Daten mit langen Folgen gleicher Zeichen wie Schwarzweißbildern. Das Verfahren wird demnach häufig für FAX-Formate verwendet. Dort treten nämlich große weiße Flächen die durch schwarze Buchstaben unterbrochen werden auf.
block separator
Interaktion
  • Auch Run Length Encoding = RLE
  • Codiert Folgen identische Zeichen durch Zähler
    • Zähler wird ab vier identischen Zeichen verwendet
    • Beispiel (! = Escape Symbol)
      • Originaltext: ABCCCCCCCDEEEEEEFGGG
      • RLE - komprimiert: ABC!7DE!6FGGG
    • Beispiel (! Im Text)
      • Originaltext: A1B2CCCCCCCCCDEEEEEFGGG!
      • RLE - komprimiert: A1B2C!9DE!5FGGG!0
  • Verwendung: für Daten mit langen Folgen gleicher Zeichen (wie Schwarzweißbildern (FAX))

block separator
PU separatorWechsel zu LOD1.Wechsel zu LOD3
LZ-Kodierung
Der Komprimierungsalgorithmus kodiert nicht einzelne Zeichen, sondern ganze Wörter. Für die Kompression eines Textes gibt es eine Tabelle mit allen im Text vorkommenden Wörtern. Für jedes Wort gibt es einen entsprechenden Index (Codewort). Anstatt nun die einzelnen Zeichen des Wortes zu kodieren wird nur der Tabellenindex für das Wort gespeichert (übermittelt). Der Decoder kann dann den Index mit Hilfe derselben Tabelle in den Ausgangstext zurückverwandeln. Ein solcher Algorithmus wird auch als ‚Wörterbuchbasiert’ bezeichnet, da die Tabelle einem Wörterbuch entspricht.
block separator
Beispiel
Man verwendet den LZ-Algorithmus um eine Textdatei zu komprimieren. Die durchschnittliche Wortlänge beträgt 6 und das Wörterbuch fasst 4096 Einträge. Wie groß ist die Kompression verglichen mit einer 7-Bit ASCII Codierung?
Im Allgemeinen kann ein Wörterbuch mit Indizes von n Bit 2 hoch n Einträge haben. Da das Wörterbuch 4096 Einträge fasst, muss man für den Index 12 Bit verwenden, da 2 hoch 12 = 4096.
Mit 7-Bit ASCII Codierung benötigt man für 6 Zeichen 42 Bits. Durch die Verwendung von Indizes hingegen nur 12. Kompressionsrate = 42 : 12 = 3,5 : 1

block separator
Viele lange Wörter im Text bringen in Summe gute Kompressionsraten, kurze Wörter bringen schlechtere Ergebnisse, da die Ersparnis geringer ist. Eine Vorraussetzung für das Verfahren ist, dass das gleiche Wörterbuch beim Codierer und Dekodierer vorhanden ist. Es gibt aber ein erweitertes Verfahren (LZW), welches diesen Nachteil umgeht.
PU separatorWechsel zu LOD1.Wechsel zu LOD3
LZW-Kodierung
Der Name dieser Codierung leitet sich aus den Namen der beteiligten Entwickler ab: Lempel, Ziv und Welsh. Beim LZW-Algorithmus bauen sowohl Encoder und Decoder den Inhalt des Wörterbuchs dynamisch auf. Das heißt, es muss kein vorgegebenes Wörterbuch statisch bei Empfänger und Sender vorliegen, sondern wird beim Einlesen der Nachricht sukzessive aufgebaut. Als Anfangswerte beinhalten beide Wörterbücher den Zeichensatz, mit dem die Nachricht erstellt wurde (z.B. ASCII). Die anderen Einträge werden erst nach und nach erstellt. Wenn der Zeichensatz beispielsweise 128 Zeichen enthält und das Wörterbuch auf 4096 Wörter beschränkt ist, dann sind die ersten 128 Einträge die Buchstaben und Sonderzeichen. Die restlichen 3968 Einträge enthalten Wörter mit einer Mindestlänge von zwei Zeichen. Je öfter ein Wort vorkommt oder je länger die Wörter sind, desto besser ist die Kompression. Im Wörterbuch werden nur alphanumerische Zeichenfolgen abgelegt und alle anderen Zeichen werden als Worttrennzeichen interpretiert.
block separator
Beispiel
Der zu komprimierende Text sei: This is simple as it is
Anfangs beinhalten die Wörterbücher von Encoder und Decoder jeweils die Einträge des individuell verwendeten Zeichensatzes. Deshalb kann das erste Wort (This) nur durch die Indizes der einzelnen Zeichen gesendet werden. Wenn der Encoder nun das Leerzeichen liest, erkennt er dieses als Trennzeichen und somit als Wortende. Es wird ebenfalls der Index vom Leerzeichen gesendet und zusätzlich das vorhergehende Wort in die nächste freie Position ins Wörterbuch geschrieben (Abbildung, Position 128).
Der Decoder macht das ganz ähnlich. Er liest die Indizes der einzelnen Buchstaben, um den Text zu rekonstruieren. Sobald der Leerraum erreicht ist, wird der Worteintrag im Decoder-Wörterbuch gesetzt. Diese Vorgehensweise setzt sich auf beiden Seiten so fort (für die Wörter is, simple, as). Bevor ein Wort durch die Codes der einzelnen Zeichen gesendet wird, überprüft der Encoder ob das Wort schon im Wörterbuch eingetragen ist. Wenn dies der Fall ist, braucht nur der Index des Wortes übermittelt werden. Genauer betrachtet heißt das, sobald ein Wort ein zweites Mal vorkommt, kann das Einsparungspotential genutzt werden, denn genau dann ist es schon im Wörterbuch auf beiden Seiten abgelegt. Dieser Fall tritt beim zweiten Vorkommen des Wortes ‚is’ ein. Nun müssen nicht die Codes der einzelnen Zeichen übermittelt werden, sondern nur der Index der im Wörterbuch auf dieses Wort verweist .
Abbildung LZW Wörterbuch mit 8 Bit Index
LZW Wörterbuch mit 8 Bit Index
Spezielle Zeichen des ASCII Zeichensatzes:
  • nul (null): Marker für das Ende von Zeichenfolgen; stark benutzt in Programmiersprachen wie C
  • del (delete): Löschen des vorangehenden Zeichens

block separator
PU separatorWechsel zu LOD1.Wechsel zu LOD3
Statistische Kodierung
Verschiedene Zeichen müssen nicht notwendigerweise auf eine feste Anzahl von Bits abgebildet werden. Dieses Prinzip wurde schon vor Beginn des Computerzeitalter vom Morsecode genutzt: Häufig auftretende Zeichen werden auf kurze Zeichenfolge abgebildet, seltene Zeichen werden durch längere Sequenzen kodiert. Eine statistische Codierung verwendet also Wahrscheinlichkeiten von Zeichen, um möglichst optimal zu kodieren. Dabei muss die Eindeutigkeit des Dekodierens gewährleistet sein (Das Codieren muss reversibel sein). Die bekanntesten Verfahren dieser Gruppe sind die Huffman und die arithmetische Codierung.
PU separatorWechsel zu LOD1.Wechsel zu LOD3
Huffman Kodierung
Für die Huffman Codierung seien die zu kodierenden Zeichen mit der Wahrscheinlichkeit ihres Auftretens gegeben. Der Huffman Algorithmus ermittelt dann die Kodierung eines Zeichens mit der minimalen Anzahl benötigter Bits für die vorgegebene Auftrittswahrscheinlichkeit. Dabei wird eine Codetabelle aufgebaut, die jedem Zeichen eine Bitfolge zuordnet. Die Länge der Bitfolgen sind hier je nach Zeichen unterschiedlich.
Die Codetabelle kann auch als binärer Baum dargestellt werden, bei dem jeder Knoten jeweils eine Kante mit der Beschriftung 0 und 1 hat. Die Blätter des Baums entsprechen den kodierten Zeichen. Gerade für das Dekodieren beim Empfänger eignet sich diese Darstellung: Beginnend von der Wurzel folgt man je nach 0 oder 1 im Code den jeweiligen Ast. Dies setzt man fort, bis man ein Blatt erreicht. Die Bezeichnung des Blattes entspricht dem dekodierten Zeichen. Nun setzt man den Algorithmus ausgehend von der Wurzel des Baumes fort.
Der Huffman Algorithmus baut den Codebaum rekursiv auf, indem er die zwei Zeichen mit den geringsten Wahrscheinlichkeiten zu einem Teilbaum zusammenfasst. Dieser Teilbaum wird zu einem neuen Symbol mit dem Wahrscheinlichkeitswert der Summe der Einzelwahrscheinlichkeiten. Dieses neue ‚kombinierte’ Symbol wird in den folgenden Schritten des Algorithmus weiter berücksichtigt. Die Kanten des Teilbaums werden mit 0 und 1 beschriftet. Diese Vorgehensweise wird nun rekursiv auf die neue Symbolmenge ausgeführt, bis alle Symbole zusammengefasst sind.
block separator
Beispiel
Gegeben seien die fünf Symbole der Quelle a, b, c, d, e mit den zugehörigen Wahrscheinlichkeiten.
Abbildung Aufbau Huffman Codebaum
Aufbau Huffman Codebaum
Anfangs werden jeweils die zwei Symbole mit den kleinsten Wahrscheinlichkeiten zu einem neuen zusammenfasst. Gleichzeitig ergibt sich durch diesen Schritt ein Teilbaum. Als Resultat erhält man den Codebaum bzw. die Codetabelle.
Abbildung Huffman Codebaum
Huffman Codebaum
Um fünf Symbole binär zu kodieren sind normalerweise 3-Bit notwendig. Anstatt der festen 3-Bit Codierung werden jetzt einige Zeichen kürzer kodiert und zwar die mit hoher Auftrittswahrscheinlichkeit. Ein Text, der Huffman kodiert ist dadurch kürzer. Um die Kompressionsrate zu bestimmen, errechnet man zuerst die durchschnittliche Wortlänge für die Huffman Codierung: 0,36 * 2 + 0,22 * 2 + 0,16 * 2 + 0,14 *3 +0,12 * 2 = 2,26 Bits/Zeichen Im Vergleich zur 3-Bit Codierung ergibt sich eine Kompression auf 75,3 % da 2,26/3=0,75333 ist.

block separator
Im vorgestellten statischen Huffman-Verfahren müssen Sender und Empfänger die Codetabelle kennen, bzw. über die Wahrscheinlichkeiten Bescheid wissen. Es gibt eine andere Variante des Huffman-Algorithmus, der unter dem Namen ‚Dynamische Huffman-Codierung’ bekannt ist. Hier wird der Codebaum dynamisch, also während der Übermittlung aufgebaut.
PU separatorWechsel zu LOD1.Wechsel zu LOD3
Arithmetische Kodierung
Das Prinzip der arithmetischen Codierung ist die Darstellung einer Nachricht als Intervall in den rationalen Zahlen. Die arithmetische Codierung hat, wie die Huffman Codierung, Wahrscheinlichkeiten als Ausgangspunkt. Aus der Sicht der Informationstheorie sind beide Codierungen optimal. Im Gegensatz zu anderen Verfahren werden durch eine Bitfolge mehrere Zeichen kodiert, dabei wird ein einzelnes Quellsymbol durch eine gebrochene Anzahl an Bits kodiert und nicht wie es sonst der Fall ist durch eine ganzzahlige Anzahl. Abgesehen von der Hardwarebeschränkung für die Rechengenauigkeit ist damit absolut redundanzfreie Komprimierung möglich.
Während die Huffman Codierung jedes einzelne Zeichen isoliert betrachtet, wird bei der arithmetischen Codierung das aktuelle Zeichen unter Berücksichtigung der vorangegangenen kodiert. Deshalb muss ein arithmetisch kodierter Datenstrom immer von Anfang an gelesen werden, ein wahlfreier Zugriff ist daher nicht möglich.
block separator
Beispiel
Die Zeichen a, b, ctreten mit einer relativen Wahrscheinlichkeit von 0.2, 0.2 und 0.6 auf. Die Zeichenfolge ‚ cbb’ soll nun kodiert werden.
Jede Zeichenfolge wird auf eine rationale Zahl zwischen 0 und 1 abgebildet. Dieses Intervall wird nach den Auftrittswahrscheinlichkeiten der Zeichen partitioniert (siehe Abbildung). Die Zahlen in den Intervallen entsprechen je einem bestimmten Zeichen. Ausgehend vom Intervall des ersten Buchstaben cwird dieses Intervall rekursiv nach den Auftrittswahrscheinlichkeiten der Zeichen geteilt.
Abbildung Arithmetische Codierung
Arithmetische Codierung
Die Zeichenfolge cbbwird als beliebige Zahl zwischen den Werten kodiert (gelbes Kästchen in der Abbildung). Die blaue Strecke ist 0.6 * 0.6, die orange ist 0.6 * 0.2 * 0.6 und die grüne 0.6 * 0.2 * 0.8 lang. In der Praxis werden die binären Gleitkommazahlen für obere und untere Intervallgrenzen berechnet und der obere Wert nach der ersten Stelle abgebrochen, welche vom unteren Wert verschieden ist.
0.45610 = 0.0111...2, 0.43210 = 0.0110…2.
Die beiden Werte unterscheiden sich in der 4. Nachkommastelle. Der Code für cbblautet demnach 0111.

block separator

PU separator
Hannes Eichner (heichner@edu.uni-klu.ac.at)
IAS, Universität Klagenfurt