En av de mest brukte komprimerings- og dekomprimeringsalgoritmene kalles LZW-metoden - etter forskerne A.Lempel, J.Ziv og T.Welch. F.eks. er det den algoritmen som ligger under GIF-formatet for grafikk på internett.
Ziv og Lempel publiserte i 1978 en metode som i dag går under navnet LZ78-metoden. Idéen gikk ut på å bygge opp en «ordbok» mens filen leses. Hvert nytt «ord» på filen legges inn i «ordboken» og får samtidig tilordnet en tallkode. Hvis et «ord» (eller egentlig en tegnsekvens) blir funnet i «ordboken» blir «ordet» isteden representert ved hjelp av tallkoden. Hvis tallkodene i gjennomsnitt blir kortere enn ordene, så får vi en komprimering. Problemet var at ideen ikke lot seg implementere på en enkel og effektiv måte. Men ved hjelp av en smart idé som T.Welch fikk i 1984, fikk metoden sitt store gjennombrudd.
Komprimering
Anta at vi har en sekvens med ascii-tegn (f.eks. en String, en fil eller lign.) I starten har vi egentlig ingen ord i ordboken. De 256 «ordene» som kun består av ett tegn har jo i utgangspunktet fått tilordnet en tallkode - tegnets ascii-verdi. Derfor er det ikke nødvendig å legge disse «ordene» inn i ordboken.
Komprimering med LZW kan beskrives slik:
Eksempel: Gitt tegnsekvensen ABBABABAC Algoritmen vil da etter 6 «runder» ha produsert flg. ordbok og utskrift av tallkoder:
runde | s | c | kode | nestekode | ordbok | utskrift |
0 | A | A | 65 | 256 | ||
1 | B | B | 66 | 257 | AB - 256 | 65 |
2 | B | B | 66 | 258 | BB - 257 | 66 |
3 | A | A | 65 | 259 | BA - 258 | 66 |
4 | AB | B | 256 | |||
5 | A | A | 65 | 260 | ABA - 259 | 256 |
6 | AB | B | 256 | |||
7 | ABA | A | 259 | |||
8 | C | C | 67 | 261 | ABAC - 260 | 259 |
9 | 67 |
Dekomprimering
Ved dekomprimering har vi en sekvens med tallkoder der første < 256. Nå skal vi bruke tallkodene til å bygge opp den samme ordboken som vi bygget opp under komprimeringen.
Dekomprimering med LZW kan beskrives slik:
Java-kode
public static void komprimerTilKonsoll(String melding) { char c = melding.charAt(0); String s = "" + c; int kode = c; int nestekode = 256; Map<String,Integer> ordbok = new TreeMap<String,Integer>(); for (int i = 1; i < melding.length(); i++) { c = melding.charAt(i); Integer ordkode = ordbok.get(s + c); if (ordkode == null) { System.out.println(kode + " " + Integer.toBinaryString(kode)); ordbok.put(s + c, nestekode); nestekode++; s = "" + c; kode = c; } else { kode = ordkode; s = s + c; } } System.out.println(kode); } // komprimerTilKonsoll public static void dekomprimerFraTabell(int[] a) { int kode = a[0]; // første tallkode - er < 256 int nestekode = 256; String denne = "" + (char)kode; // første tegn String forrige = null; char c; System.out.print(denne); // denne skrives ut Map<Integer,String> ordbok = new TreeMap<Integer,String>(); for (int i = 1; i < a.length; i++) { kode = a[i]; forrige = denne; if (kode < nestekode) { denne = kode < 256 ? "" + (char)kode : ordbok.get(kode); c = denne.charAt(0); } else { c = forrige.charAt(0); denne = forrige + c; } System.out.print(denne); ordbok.put(nestekode,forrige + c); nestekode++; } } // dekomprimerFraTabell
Copyright © Ulf Uttersrud, 2011. All rights reserved.