# Compression de données/Codage par dictionnaire

* Introduction
* Types de compression
* Techniques de compression sans perte
** Codage par répétition
*** Run-length encoding
** Codage entropique
*** Codage de Huffman
*** Codage de Shannon-Fano
** Codage par dictionnaire
*** Lempel-Ziv-Welch (LZW)
** Codage par modélisation de contexte
** Transformée de Burrows-Wheeler
** Archive de fichiers
* Techniques de compression avec pertes
** Le format JPEG 2000
* Taux de compression
* Bibliographie et liens
* Introduction
* Types de compression
* Techniques de compression sans perte
** Codage par répétition
*** Run-length encoding
** Codage entropique
*** Codage de Huffman
*** Codage de Shannon-Fano
** Codage par dictionnaire
*** Lempel-Ziv-Welch (LZW)
** Codage par modélisation de contexte
** Transformée de Burrows-Wheeler
** Archive de fichiers
* Techniques de compression avec pertes
** Le format JPEG 2000
* Taux de compression
* Bibliographie et liens
[ Modifier le sommaire ]

## Principe

La compression par dictionnaire utilise le fait que certaines séquences d'octets consécutifs sont répétées. Si une telle séquence a déjà été vue auparavant, au lieu de d'écrire la longue séquence, une référence à la séquence originale est écrite, donnant de manière la plus compacte possible le décalage où trouver la séquence à copier et sa longueur.

## Algorithmes

LZ77 et LZ78 sont deux algorithmes de compression de données sans perte proposés par Abraham Lempel et Jacob Ziv en 1977 et 1978 (d'où leurs noms). Ces deux algorithmes posent les bases de la plupart des algorithmes de compression par dictionnaire, à tel point qu'on parle couramment d'algorithme LZ pour désigner un algorithme de compression par dictionnaire. Ces algorithmes reposent de manière essentielle sur une mesure de complexité pour les suites de longueur finie, la complexité de Lempel-Ziv.

## LZ77
### Principe

LZ77 est un algorithme de compression par dictionnaire utilisant une fenêtre glissante ; les motifs déjà rencontrés dans la fenêtre sont remplacés par une référence à leur première apparition (typiquement, par une paire (distance, longueur)).
Par extension, LZ77 est aussi utilisé pour désigner la famille des algorithmes de compression par dictionnaire utilisant une fenêtre glissante, comme LZSS et LZMA.

### Description de l'algorithme LZ77
#### Compression

Étant donnée une séquence S à compresser, on l'écrit d'abord sous forme de plusieurs composantes S$_i$ juxtaposées. Pour ce faire, on choisit un entier L$_S$ qui sera la longueur maximale d'un S$_i$ et un entier n > L$_S$ qui sera la taille du buffer. On initialise les n-Ls caractères du buffer par des zéros et on complète le buffer par les L$_S$ premiers caractères de S.
L'entier n-Ls est la taille de la fenêtre glissante (initialisée avec des zéros comme indiqué précédemment). Pour trouver les S$_i$, on réalise à chaque itération une production exhaustive de la sous-séquence de S la plus longue possible en prenant le contenu de la fenêtre glissante comme préfixe, avec ici la contrainte que la longueur de la séquence produite ne peut dépasser Ls.
Après initialisation de la fenêtre à zéro et en appliquant ce processus de production on obtient donc la séquence S$_1$ de longueur L$_1$<Ls puis on fait glisser la fenêtre en enlevant les L$_1$ premiers caractères de la fenêtre glissante du buffer et en faisant entrer dans le buffer les L$_1$ caractères suivants de S. On répète ce procédé (production puis glissement de la fenêtre) pour trouver les autres S$_i$ jusqu'à arriver au bout de la séquence S.
Cette décomposition découpe S sous forme de composantes comme dans le processus de calcul de la complexité de Lempel-Ziv.
À chaque étape i, après avoir trouvé S$_i$ par un processus de production, on lui affecte un mot de code qui sera sa représentation dans le fichier compressé. Ce mot de code n'est rien d'autre que le triplet (position, longueur, caractère) correspondant.
Chaque S$_i$ est ainsi codé par un triplet C$_{i,1}$C$_{i,2}$C$_{i,3}$ et sera représenté ainsi dans le fichier compressé. Le mode de représentation est donc le suivant :
* C$_{i,1}$ est la représentation en base α(α étant la taille de l'alphabet des caractères de S) de p$_i$-1, avec p$_i$ l'indice dans la fenêtre glissante où commence la copie qui correspond à S$_i$(p$_i$ est le pointeur pour la production de S$_i$).
* C$_{i,2}$ est la représentation en base α de L$_i$ - 1 (la longueur de la production à cette étape)
* C$_{i,3}$ est le dernier caractère de S$_i$
Cet algorithme est étroitement lié au calcul de complexité de Lempel-Ziv. Après avoir fait précédé S de n-L$_S$ zéros, on ne fait en effet que décomposer S en composantes S$_i$ (qu'on remplace par leur mot de code) en prenant, à chaque étape, le contenu de la fenêtre glissante comme préfixe et en ayant une longueur maximale L$_S$ fixée pour toutes les composantes.
Vu que p$_i$ est un indice appartenant au préfixe (ici, la fenêtre glissante), il est compris entre 1 et n-L$_S$ et peut être représenté en base α par $\lceil \log$ $_α$ (n-L$_S$)$\rceil$ caractères. De même, les L$_i$ étant bornés par L$_S$, on a besoin de $\lceil \log$ $_α$ (L$_S$)$\rceil$ caractères pour représenter L$_i$-1. C$_{i,3}$ étant un caractère unique, chaque S$_i$ sera représenté dans le fichier compressé par L$_C$ =$\lceil \log$ $_α$ (n-L$_S$)$\rceil$+ $\lceil \log$ $_α$ (L$_S$)$\rceil$ + 1 caractères.

#### Décompression

La décompression est très semblable à la compression.
Initialisation :
* on utilise une fenêtre de taille n-L$_S$ qui est initialisée avec des zéros,
* on récupère p$_i$ - 1 (et donc p$_i$) sur les $\lceil \log$ $_α$ (n-L$_S$)$\rceil$ premiers caractères de C$_i$ (C$_{i,1}$),
* les $\lceil \log$ $_α$ (L$_S$)$\rceil$ caractères suivants (C$_{i,2}$) donnent la valeur de L$_i$ - 1.
Après l'initialisation, à chaque étape i on répète L$_i$ -1 fois le processus suivant :
* on recopie le caractère qui est à l'indice p$_i$ à la fin de la fenêtre,
* puis on fait glisser la fenêtre vers la droite pour faire sortir son premier caractère et faire entrer le caractère qui vient d'être recopié dans la fenêtre.
Vu que les L$_i$ - 1 premiers caractères de S$_i$ sont juste une copie de la partie de la fenêtre commençant à l'indice p$_i$, on récupère par le processus ci-dessus les L$_i$-1 premiers caractères de S$_i$. À ce stade, il ne nous manque que le dernier caractère de S$_i$ qui n'est rien d'autre que le dernier caractère (C$_{i,3}$) de C$_i$.
Ceci amène à la dernière phase de l'étape i qui consiste à :
* recopier le dernier caractère de C$_i$ (qui est le dernier caractère de S$_i$) à la fin de la fenêtre avant d'effectuer un dernier décalage à droite, d'un caractère, de la fenêtre.
On obtient ainsi S$_i$ en récupérant les L$_i$ derniers caractères de la fenêtre. Après avoir appliqué ce processus à tous les mots de code C$_i$, la séquence S est obtenue en concaténant les S$_i$.

### Limites et utilisations

LZ77 présente certains défauts, en particulier, si aucune chaîne n'est trouvée dans le dictionnaire, le symbole à compresser est alors codé par "position=0", "longueur=0", "nouveau symbole", c'est-à-dire qu'il occupe 3 octets au lieu d'un seul dans le fichier original. Ce défaut est supprimé dans la variante LZSS.
L'algorithme LZ77 est notamment utilisé dans l'algorithme deflate (avant un codage de Huffman) et pour la compression des fichiers dans le système de fichier Windows NTFS.

## LZ78

LZ78 est un algorithme de compression par dictionnaire (publié dans anglais « Compression of Individual Sequences via Variable-Rate Coding », dans IEEE Transactions on Information Theory, septembre 1978 ) utilisant un dictionnaire global (et non plus une fenêtre), construit de la même façon par le compresseur et le décompresseur, respectivement à la compression et à la décompression. Cela permet d'éviter le principal problème de son prédécesseur (LZ77) qui ne peut retrouver une chaîne de caractères si elle se trouve en dehors de la fenêtre.
Par extension, LZ78 est aussi utilisé pour désigner la famille des algorithmes de compression par dictionnaire utilisant un dictionnaire implicite, comme Lempel-Ziv-Welch.
LZ78 a eu moins de succès que LZ77, pour des raisons d'efficacité, et parce qu'il a été protégé par un brevet logiciel aux États-Unis.

## Références

* ↑ NTFS