Plan... Qu'est-ce que la compression? Pourquoi compresser? Que coûte la compression? Les types de compression Les algorithmes de compression canoniques Le Run Length Coding (RLC) La compression Topologique La compression Relative Les Algorithmes de compression Statistique Les Algorithmes de compression de Type Dictionnaire Les Algorithmes de compression Hybrides
Plan... Exemples d’algorithme de compression sans perte L’algorithme de Huffman (statistique) Le principe L’algorithme ce compression L’algorithme de décompression Exemple d’application L’algorithme de Shanon – Fado (statistique) L’algorithme de compression-décompression Un exemple d'application Comparaison Huffman vs Shanon-Fado L’algorithme Arithmétique (statistique)
Plan... L’algorithme LZ87 L’algorithme LZSS L’algorithme LZW (première variante : Association de codes variables aux motifs) Un exemple d'application L'algorithme de codage/décodage LZW : Spécificités de LZW : L’algorithme LZW (première variante : Association de codes fixes aux motifs) Le principe Les algorithmes Phase de compressions Phase de décompression Limites et améliorations
Plan... Utilisation des algorithmes de compression Sous Unix/Linux Gzip , Gnozip Sous Windows Power Archive, Winzip La Compression Dédiée La compression Dédiée : Le Son L’étude du phénomène L'algorithme PASC La compression Dédiée : L'image La norme JPEG La Compression Vidéo La norme MPEG
La compression, c’est quoi? Chacun pratique la compression couramment: de la prise de note au départ en voyage, chaque fois qu'on souhaite stocker ou déplacer des objets ( ou de l'information ) avec des moyens restreints, le besoin de compresser se fait sentir. Déja, dans ce cadre très courant se dessinent les grandes tendances de la compression informatique: lorsqu'on cherche à exploiter chaque coin de la valise, lorsqu'on saute dessus pour parvenir à la fermer, on pratique une compression sans perte. Si, en revanche, on décide de ne pas emporter, cette fois-ci, le téléviseur, on réalise une compression avec perte : un choix raisonné nous a permis d'exclure le superflu. En informatique, la compression des données ou des fichiers consiste en la réduction de la taille physique de blocs d'informations. Un compresseur utilise un algorithme qui sert à optimiser les données en utilisant des considérations propres au type de données à compresser, un décompresseur est donc nécessaire pour reconstruire les données originelles grâce à l'algorithme inverse de celui utilisé pour la compression.
Pourquoi compresser? La compression des données trouve d'abord sa justification dans l'histoire de l'informatique: En 1985 un disque dur de 33 Mo coûtait quelques centaines de dollars: c’est pourquoi les utilisateurs de l'époque ne souhaitaient pas stocker de longues répétitions de blancs par exemple. Aujourd'hui, si les moyens de stockage semblent plus accessibles, la quantité de données à stocker a augmenté en proportion, quand aux «autoroutes de l'information», elles sont plus que jamais saturées par les nouveaux besoins du multimédia. La compression permet, dans une certaine mesure, de pallier de façon spectaculaire aux limites du matériel.
Pourquoi compresser? Les objectifs de compression les plus importants sont les suivants : Pour le transfert : => Réduire le temps nécessaire au transfert d’un fichier sur un réseau (envoi d’un fichier dans un courrier électronique, transfert de fichiers entre ordinateurs, etc.). Le coût : $$$ => Réduire les coûts de communications puisque le réseau est utilisé moins longtemps (cas du transfert de fichiers via un modem et une ligne téléphonique par exemple). Pour le stockage : => Placer sur un support de petite taille tel qu’une disquette un fichier qui était auparavant trop volumineux pour contenir sur un tel support.
Les classes de compression... Deux types d'algorithmes visant à réduire la taille des données manipulées: les algorithmes de compression sans perte et les algorithmes de compression avec perte. Les algorithmes de compression avec perte visent à restituer une information réduite à l'utilisateur. Ils peuvent supporter un certain taux de perte pour des signaux comme le son ou la vidéo. Ces algorithmes dits algorithmes de (compression destructive). Les algorithmes de compression sans perte réduisent la taille des données sans perte d'information (ou compression non-destructive) et forment donc une sous-classe de la classe des algorithmes de compression.
Le compression sans perte (canonique) ... Les algorithmes de compression sans perte (compactage) ne visent qu'un seul et même objectif: l'élimination de la redondance dans les fichiers. Les fichiers informatiques traditionnels étant d'origine humaine ou décrivant des formats numériques répétitifs, et les langues humaines étant notoirement redondantes (l'anglais est redondant à 75 %), les-dits fichiers contiennent une part importante d'information non pertinente.
RLC (ou RLE)... La méthode RLC (Run Length Coding), qui est parfois appelée RLE (Run Length Encoding) est sans doute une des plus simples méthodes qui soit. La compression consiste simplement à remplacer une séquence de n octets identiques de valeur v par : - cnv (dans le cas des données textuelles) - le couple (n,v) dans le cas des images Où c : est un caractère spécial de compression Pour appliquer le RLC, il suffit de se choisir un caractère de contrôle #, et de coder les plages de k octets par : # octet k. Un exemple d'utilisation est donné dans la figure suivante :
RLC (ou RLE)... Autre exemple : (compression des images) Soit la suite de pixels suivante: 11 octets en utilisant la convention 0 = noir, 1 = blanc, elle est codée sous la forme: (4,0),(3,1),(2,0),(2,1) : 8 octets en considérant que chaque pixel est codé sur un octet et chaque couple sur 2 octets, on obtient bien une compression: 8 octets au lieu de 11 octets. l'exemple suivant montre une faiblesse de cette méthode: est codé (1,0),(1,1),(1,0),(1,1),(1,0),(1,1),(1,0),(1,1),(1,0),(1,1),(1,0) La forme 'compressée' prend 2 fois plus de place que l'original. Mais pour éviter ce problème, les format utilisant le RLE introduisent une convention permettant de créer des séquences de pixels indépendants, codés sur un octet.
La compression topologique... On choisi un octet O dont on va privilégier la compression: on va lire des blocs de huit octets puis remplacer les occurrences des octets O par un octet de description en tête de séquence qui indique les emplacement des octets O. Ne reste dans la séquence que les octets différents de O. Un exemple est donné ci-dessous dans la figure suivante: On peut itérer ce procédé avec d'autres octets mais l'efficacité décroît très vite du fait du stockage du bit de description qui interdit une compression inférieure à 9/8. On est ici en face des problèmes posés par le stockage des descriptions d'occurrence qui resurgiront plus tard.
Le codage relatif... Le codage relatif est utilisé pour la compression de données numériques et plus précisément de mesures. Il n'est en effet pas rare que des mesures tels la température soit sous une forme numérique peu économique : des entiers sur 32 bits, ou même des réels. Dans le cadre du codage relatif on résume les bits qui ne varient pas en début de séquence, puis on ne précise que les bits qui évoluent. Exemple : Ainsi si les données en entrée sont : 00010001 00010110 00010111 Le compacté sera : #5 00010 4 101 001 110 111 5 indique le nombre de bits constants, 4 le nombre de mesures. Le reste est évident. Ce codage est très pratique pour coder les résultats d'expérience.
fichier = f( M1, M2, Mn ) et fi = fréquence(Mi) Les algorithmes de compression statistique... Les algorithmes de codage statistique forment une autre classe d'algorithmes. On considère le fichier f comme un ensemble de motifs quelconques Mi dont on va étudier les fréquences d'apparition fi. fichier = f( M1, M2, Mn ) et fi = fréquence(Mi) Après avoir calculé les fréquences d'apparition fi, on va établir un codage Ci des motifs de telle sorte que les tailles des code Ci soit inversement proportionnelles aux fréquences d'apparition des motifs Mi. Ainsi pour un ensemble de motifs donné on obtiendra une compression optimale. Le fichier compacté sera composé de la liste des correspondances (Mi,Ci) et du fichier f où on aura remplacé Mi par Ci. La chaîne de compression statistique est résumée dans la figure ci-dessous.
Les algorithmes de compression statistique...
Les algorithmes de compression statistique... Etape1 : Choix des motifs Cette étape est primordiale car le compactage est optimal pour un ensemble de motif donné. Un bon ensemble de motifs est un ensemble réduit numériquement pour éviter des tables de fréquences surdimensionnées, et suffisamment important pour rendre compte de la diversité du fichier. L'unité courante est l’octet : 255 motifs de huit bits, et on parle de compression de 1er ordre. On peut aussi choisir des paires d'octets : 255^2 motifs et on parle de compression d'ordre 2. Au-delà les tailles des tables de fréquences sont prohibitives.
Les algorithmes de compression statistique... Étape 2 : Calcul des fréquences Le calcul des fréquences ne pose aucun problème théorique. Cependant il impose de parcourir au moins une fois le fichier. Il en découle l'obligation de parcourir au moins deux fois le fichier étudié : une fois pour calculer les fréquences, une fois pour remplacer les motifs, ce qui pour un long fichier pose problème.
Les algorithmes de compression statistique... Étape 3 : Élaboration des codes L'élaboration des codes est l'étape la plus complexe. Le problème est de trouver un algorithme efficace qui permette d'établir à partir d'une liste (fréquence, motif) des codes Ci efficaces. C'est à cette question que répondent les algorithmes de Huffman et de Shanon-Fado.
Les algorithmes de compression statistique... Étape 4 : Création du compacté Le compacté est composé de la liste des associations codes-motif et du fichier où les codes ont remplacé les motifs. L'obligation de stocker une table avec le fichier diminue l'efficacité du compacteur et limite la taille des motifs (etape 1).
Les algorithmes de compression statistique... Les algorithmes de codage statistique ne s'intéressent qu'à un ensemble de motifs et à leur redondance statistique, mais aucunement à leur agencement. Les deux séquences suivantes donneront les même performances en compression : Exemple: AAAAAAAAAAAAAAABBBBBBBBBBBBBBBBB et ABABABABABABABABABABABABABABABAB Ils ne détectent donc ni les redondances de positions, ni l'existences de groupes de motifs redondants, tâche dont s'acquittent brillamment les algorithmes de type dictionnaires. Dans la section «Exemples d’algorithmes de compactage», on va voir quelques exemples d’algorithmes de compression statistiques.
Les algorithmes de type dictionnaire... Ils établissent un dictionnaire des termes employés dans un fichier, termes qui peuvent êtres de taille quelconques, et leur associent un code de taille moins importante. Le fichier compacté est composé du dictionnaire et du fichier où les termes auront été remplacés par les codes. Le fonctionnement de tels algorithmes est résumé dans la figure ci-dessous.
. A ce niveau les algorithmes de type dictionnaire permettent de détecter des redondances avec un ensemble de motifs de taille quelconque, et en ne parcourant le fichier qu'une seule fois, le dictionnaire pouvant être établi au cours de la lecture du fichier. Le gain est appréciable mais pas déterminant. C'est l'existence de l'algorithme LZW qui donne à cette classe de compresseur tout son intérêt : il permet de compacter en une seule étape le fichier sans stocker le dictionnaire. C'est le décompresseur qui va reconstruire le dictionnaire initial à partir du fichier compressé. Dans la section «Exemples d’algorithmes de compactage», on va voir deux variantes de l’algorithme LZW.
Les algorithmes hybrides... Les programmes de compression les plus performant combinent la puissance des algorithmes de type dictionnaire (comme LZW) et l'efficacité des algorithmes statistiques pour compresser les motifs redondants. La combinaison est simple : Aux algorithmes de type dictionnaire de détecter les redondances dans les fichiers et de constituer les dictionnaires de motifs redondants. Aux algorithmes statistiques de trouver les codages les plus concis pour les termes contenus dans les dictionnaires. Ce sont ces méthodes qui sont utilisées dans les programmes tels LHA, ZOO, ARJ et PKzip. L'équation résumant le fonctionnement de ces programmes sont donné dans la figure suivante.
. .
Supposons que nous voulions coder cette phrase. L’algorithme de Huffman... Supposons que nous voulions coder cette phrase. * ASCII : Si on va coder cette chaîne de caractères, la méthode la plus simple est d’utiliser le code ASCII. Le tableau suivant présente les caractères de notre chaînes ainsi que les codes ASCII correspondants. Puisqu'on sait que chaque caractère est codé sur 8 bits, on n'a pas besoin de séparateur ; le message codé est le suivant: 01010011011101010111000001110000 ... 00101110 . Il occupe 47*8=376 bits. symbole code binaire S 83 01010011 u 117 01110101 p 112 01110000 o 111 01101111 s 115 01110011 ... . 46 00101110
L’algorithme de Huffman... * Codage fixe : On peut arriver à un codage plus économique, en remarquant que les seuls caractères utilisés sont S, u, p, o, s, n, blanc, q, e, v, l, i, c, d, r, t, h, a, et point, soit 19 caractères. Le message devient : 0000000001000100001000011 ... 10010 , et n'occupe plus que 47*5 = 235 bits< 376 bits. Mais avec ce type de codage, on ne peut pas présenter tous les caractères. symbole code binaire S 00000 u 1 00001 p 2 00010 o 3 00011 s 4 00100 ... . 18 10010
L’algorithme de Huffman... * Codage optimal : Étudions les fréquences des caractères employés : symbole fréquence S 1 u 4 p 3 o 6 s 5 n blanc q e v l i c 2 d r t h a .
L’algorithme de Huffman... Ordonnons les par fréquence décroissante, et numérotons les . Associons un code binaire du numéro d’ordre de chaque caractère. symbole fréquence numéro binaire o 6 blanc 1 s 5 2 10 e 3 11 u 4 100 p 101 n 110 c 7 111 r 8 1000 t 9 1001 S 1010 q 1011 v 12 1100 l 13 1101 i 14 1110 d 15 1111 h 16 10000 a 17 10001 . 18 10010
L’algorithme de Huffman... Nous pouvons alors coder le message par : 101010010110101001101011011100 ... 10010 ( S)(u)(p)(p)o so(n) space ( q)(u) ... ( . ) Le code binaire du message n'occupe plus que : (6*1) + (6*1) + (5*2) + (5*2) + (4*3) + (3*3) + (3*3) + (2*3) + (2*4) + (2*4) + 6*4 + 3*5 = 123 bits < 235 bits. Mais en utilisant ce type de codage, nous ne pouvons plus le décoder. Pour pouvoir les décoder, il nous faudrait un séparateur. Ce ne peut être qu'une chaine de bits que l'on est sûr de ne pas confondre avec un caractère, ni avec une succession de caractères. Par exemple, 10011 n'est pas un caractère, mais pourrait très bien être "ue", ou "blanc o o blanc blanc".
L’algorithme de Huffman... * L’idée de Huffman En utilisant ce type de codage, l’idée de Huffman consiste à ce qu'aucun code ne soit préfixe d'un autre. Nous pouvons garder "0" pour "o", puisqu'aucun autre code ne commence par "0". En revanche, nous ne pouvons pas garder "1" pour "blanc". Mais nous pouvons prendre "10", à condition de nous interdire qu'un autre code commence par "10". Il est clair que nous ne pouvons pas prendre "11" pour "s", à moins de nous interdire des codes commençant par "11", ce qui est impossible puisque nous avons déjà interdit "10xxx". Arbre binaire Formalisons le raisonnement intuitif précédent. On a : On a 47 occurrences à répartir, et il est clair qu'il faut que les caractères les plus fréquents aient le code le plus court. On affecte donc "0" aux 6 "o", il nous reste 41 occurrences à affecter.
L’algorithme de Huffman... Sion 'affecte "10" à "blanc", et "11..." au reste, on est parti pour développer une liste plate : On va bientôt dépasser les 8 bits!
L’algorithme de Huffman... Si, au contraire, on fait un arbre binaire "symétrique", c'est-à-dire avec autant de "0" que de "1" : On va aboutir... à un code de longueur fixe (la longueur sera le log du nombre de caractères). On a gâché la fréquence.
L’algorithme de Huffman... La solution est donc intermédiaire entre la liste "plate" et l'arbre "symétrique". Plus on descend, plus on laisse les sous-arbres de gauche se développer :
L’algorithme de Huffman... C'est-à-dire qu’on code Sur 1 bit le caractère le plus fréquent Sur 3 bits les deux plus fréquents restant Sur 5 bits les 4 plus fréquents restant Sur 2n+1 bits les 2n plus fréquents restant
L’algorithme de Huffman...
L’algorithme de Huffman... Avec le cas particulier final où, s'il n'en reste pas 2n, on peut nous contenter de 2n bits.
L’algorithme de Huffman... Donc, en utilisant cette idée, notre message devient : 1110011110011101011010010101101 ... 111111( S )( u )( p )( p )o(s)o( n) ... (. ) Il occupe (6*1) + (6*3) + (5*3) + (5*5) + (4*5) + (3*5) + (3*5) + (3*(2*7)) + (5*(1*7)) + (4*(1*6)) = 213 bits<235 bits. C'est plus que le codage précédent, mais, cette fois-ci, on peut le décoder. Pour le décoder, on doit suivre les étapes suivantes : On part de la racine si je trouve un "0", on va au fils gauche sinon, on va au fils droit quand il n'y a plus de fils (feuille), on a notre caractère On repart de la racine On remarque que ce code n’est pas optimal, car on aura du faire coder "c", "r" et "t" sur 6 bits.
L’algorithme de Huffman... symbole fréquence o 6 blanc s 5 e u 4 p 3 n c 2 r t S 1 q v l i d h a . L'idée de l’algorithme Si vous regardez les figures ci-dessus, votre tendance naturelle consiste à lire les arbres de haut en bas. D'ailleurs, on a construit les arbres successifs en commençant par la racine, puis en développant vers le bas. Mais, si on essaie de comprendre les nombres qui sont dans les cercleson est obligé(e) de lire les arbres de bas en haut, puisque ces nombres sont les sommes des occurrences des noeuds inférieurs. L'algorithme de Huffman part du bas, c'est-à-dire qu'il va regrouper des feuilles en petits arbres, puis fusionner ces petits arbres pour en donner de plus gros, et ainsi de suite. Donc on va commencer par les caractères les moins fréquents, de manière à ce qu'ils restent le plus bas possible, afin de garder les codes les plus courts pour les caractères les plus fréquents. Reprenons notre tableau :
L’algorithme de Huffman... On regroupe le "point" et le "a": et les autres petits, deux par deux : On trie
L’algorithme de Huffman... On regroupe deux par deux : On arrête! On retrie :
L’algorithme de Huffman... On regroupe : On retrie :
L’algorithme de Huffman... On regroupe :
L’algorithme de Huffman... Éventuellement, on retriera, mais il se trouve qu’on n'en a pas besoin, alors on regroupe:
L’algorithme de Huffman... On retrie, et on a fini : Si on fait le calcul on va trouver : 185 bits. Avec cette idée, on démontre que le codage obtenu est optimal.
L’algorithme de Huffman... L’idée de l’algorithme d'encodage lire le texte à coder Exemple : '("S" "u" "p" "p" "o" "s" "o" "n" "s" " " "q" "u" ... ".") calculer la fréquence de chaque caractère dans le texte Mais une fonction ne renvoie qu'un résultat Oui, mais rien n'empèche ce résultat d'être : une liste de couples ((carac1 freq1) (carac2 freq2) ... (caracn freqn)) ou une liste de listes ((carac1 ... caracn) (freq1 ... freqn)) ou même ((carac1 ... caracn) freq1 ... freqn), dont le cdr est la deuxième liste voulue Exemple : (("S" 1) ("u" 4) ("p" 3) ... ("." 1)) trier la liste de couples (carac freq) suivant les fréquences croissantes Exemple : (("S" 1) ("q" 1) ("v" 1) ... ("o" 6))
L’algorithme de Huffman... construire l'arbre Exemple : (47 (20 (9 ("u" 4) ("e" 5)) (11 ("s" 5) (" " 6))) (27 (12 .... ("c" 2))))) Cela demande de savoir : -Fusionner deux feuilles Exemple : ("S" 1) et ("q" 1) -> (2 ("S" 1) ("q" 1)) -Fusionner deux arbres Exemple : (2 ("S" 1) ("q" 1)) et (2 ("v" 1) ("l" 1)) -> (4 (2 ("S" 1) ("q" 1)) (2 ("v" 1) ("l" 1))) -ou fusionner un arbre et une feuille Toutes ces opérations peuvent être réalisées par la même fonction, du moment que la fonction qui calcule le poids de chaque morceau sait faire la différence entre un arbre et une feuille. -Mettre l'arbre obtenu à la bonne place dans la liste, ce qui n'est pas difficile si la fonction de tri écrite précedemment utilise un tri par insertion. construire la table de codage Exemple : (("u" (0 0 0)) ("e" (0 0 1)) ... ("c" (1 1 1 1 1))) En partant de la racine, on met (0) quand on prend le fils gauche, (1) quand on prend le fils droit, et on "appende" jusqu'à ce qu'on trouve les feuilles. coder Exemple : (0110000011001100100 ... 110100)
L’algorithme de Huffman... l’idée de l’algorithme de décodage Etant donné une liste telle que celle ci-dessus, on peut, bien entendu, la décoder à l'aide de la table, mais la procédure est assez lourde. Il est beaucoup plus simple de repartir de l'arbre. Cependant, la procédure est un petit peu délicate, dans la mesure où : je cherche quel caractère correspond aux premiers bits, donc je parcours l'arbre mais, quand j'aurai trouvé, il faudra recommencer pour les bits suivants, donc reprendre l'arbre à la racine. Cela explique pourquoi on passe deux fois l'arbre à la fonction : une fois pour qu'elle le parcoure, une fois pour qu'elle le conserve pour l'avenir. (0110000011001100100 ... 110100) 47 47 : le car est un 0, on va à gauche (110000011001100100 ... 110100) 20 47 : le car est un 1, on va à droite (10000011001100100 ... 110100) 11 47 : le car est un 1, on va à droite (0000011001100100 ... 110100) 6 47 : le car est un 0, on va à gauche (000011001100100 ... 110100) 3 47 : le car est un 0, on va à gauche C'est une feuille, je stocke "S", et on repart avec : (00011001100100 ... 110100) 47 47
Exemple... Dans le présent exemple, nous allons effectuer les trois premières étapes d'un algorithme de compactage statistique : choix des motifs, établissement de la table des fréquences et des codes pour le compactage selon la méthode de Huffman. La chaîne que nous allons traiter est : BACFGABDDACEACG Les motifs que nous allons étudier sont les octets, donc les lettres : A, B, C, D, E, F, G
Exemple... La table des fréquences est donnée ci-dessous dans la figure suivante : on constate que les motifs ont été écrits dans la table par ordre décroissant de fréquence d'apparition.
Exemple... Ensuite commence la première étape de l'algorithme de Huffman. Son déroulement est résumé ci-dessous dans la figure suivante. Il s'agit de regrouper les motifs de plus faible fréquence comme suit : on somme leurs fréquences et on place le nombre ainsi calculé dans une nouvelle table où les deux fréquences ont été enlevées. On obtient une arborescence dite "arborescence de Huffman".
Exemple... Par suite on utilise l'arborescence de Huffman pour construire les codes binaires associés aux motifs. On attribue à la plus haute fréquence de la dernière table la valeur 0, 1 à l'autre fréquence. Ensuite on code par retour arrière de la manière suivante : à chaque bifurcation dans une table on attribue à l'antécédent de plus haute fréquence la valeur 0, à l'antécédent de plus faible fréquence la valeur 1. On obtient ainsi l'arbre "décoré" de la figure suivante. Pour obtenir les codes, il suffit de parcourir l'arbre depuis le motif étudié jusqu'à la fin du chemin en empilant les symboles binaires rencontrés sur le chemin. Les résultats de la recherche sont aussi donnés dans la figure suivante.
Exemple... On remarque que le fichier compacté sans en-tête comporte 40 bits contre 120 bits pour le fichier original.
Exemple... .
L’algorithme de Shanon – Fado... L'algorithme de Shanon-Fado est, au même titre que l'algorithme de Huffman, une solution au problème de l'élaboration des codes comme il a été posé pour les algorithmes de codage statistique. Les résultats sont équivalent à ceux de Huffman mais la méthode est radicalement différente : alors que Huffman construit un arbre en partant des feuilles pour trouver une racine, Shanon-Fado opère par divisions successives de la table des fréquences. L'écriture de l’algorithme de Shanon-Fado étant fastidieuse on commence par le donner sous une forme résumée et informelle. La connaissance de l'algorithme de Huffman peut grandement en faciliter la lecture.
L’algorithme de Shanon – Fado...
L’algorithme de Shanon – Fado... Comparaison Huffman vs Shanon-Fado : On remarque tout d'abord que la récursivité est au coeur de Shanon-Fado : il faut à chaque étape de l'algorithme scinder un table en deux. Pour Huffman il suffisait de réitérer et d'ajouter des éléments à la table des fréquences. La mise en oeuvre de Shanon-Fado est donc un peu différente de celle de Huffman. D'autre part on peut hésiter entre plusieurs partitions pour un même table quand celles-ci soient équivalentes. Alors on devra choisir la partition qui rend les rapports des sommes des fréquences des deux groupes le plus proche de 1. L'exemple donne une illustration de ce type de choix. Du point de vue de l'efficacité l'algorithme de Shanon-Fado donne de meilleurs résultats quand la dispersion des fréquences est importante.
Exemple... Dans le présent exemple nous allons effectuer les trois premières étapes d'un algorithme de compactage statistique : choix des motifs, établissement de la table des fréquences et établissement des codes pour le compactage selon la méthode de Shanon-Fado. La chaîne que nous allons traiter est : « ACBBCDECECBCEEECCCCABCECBDBDBD » Les motifs que nous allons étudier sont les octets donc les lettres :A, B, C, D, E. On commence comme pour Huffman à classer les motifs par ordre décroissant de fréquence, puis le processus de scission de la table commence. Il est résumé dans son intégralité dans la figure suivante. Ici les scissions de tables sont toujours réalisées de la même manière : on choisit dans la table à scinder le motif de plus haute fréquence qui forme à lui seul une table. L'autre table est formée par les autres fréquences de la table initiale. Remarquons que la scission systématique de table évoqué ci-dessus est un hasard. Par exemple on choisit la partition (7,5,4,2) en (7) et (5,4,2) au lieu de (7,5,4,2) en (7,5) et (4,2) car 7/11 > 6/12 (cf règle de choix).
Exemple... Par la suite comme on écrit en face de chaque table la somme des fréquences de la table, on associe à la transition vers la table singleton le bit 0, à la transition vers l'autre table le bit 1. Le cheminement est assez naturel et ne nécessite aucun retour en arrière. Sur la figure suivante la transition de C vers C est affecté par 0. Pour construire les codes il suffit de parcourir l'arbre par le chemin qui va du motif choisi vers lui-même. Ainsi, dans la figure ci-dessus, on retrouve les codes élaborés dans la dernière colonne. On remarque que le fichier compacté sans en-tête comporte 64 bits contre 196 bits pour le fichier original et ce pour un cas défavorable à l'algorithme.
L’algorithme LZW (Codage variable)... L'algorithme LZW est un algorithme de compression de type dictionnaire résolvant trés efficacement les problèmes clefs tels que le stockage et la gestion du dictionnaire. Il porte le nom de ses trois inventeurs : Lempel et Ziv qui l'ont conçu en 1977, et Welch qui l'a finalisé en 1984. Les caractéristiques essentielles de LZW sont : Il n'existe pas de table d'en-tête : le dictionnaire est construit au fûr et à mesure de la lecture du fichier tant au compactage qu'au décompactage. L'algorithme ne fonctionne pas sur un nombre fixe de motifs mais apprend les motifs du fichier durant la lecture du fichier à compacté. Le compactage se fait en une seule lecture, contre deux pour les algorithmes statistiques. On ne traitera ici une première version très simple de LZW. En effet existent de multiple variantes de l'algorithme. L'algorithme sera présenté par un exemple. On reviendra plus en détail sur les diverses spécificités de l'algorithme et sur les difficultés de programmation.
"AIDE TOI LE CIEL T AIDERA" Exemple... Nous allons traiter une chaîne par l'algorithme LZW, pour nous familiariser avec celui-ci. Ceci nous facilitera grandement la lecture de l'algorithme présenté dans la section suivante. La chaîne considérée est : "AIDE TOI LE CIEL T AIDERA" L'objectif de l'algorithme LZW est de construire un dictionnaire où une séquence qui sera désignée par une adresse dans le dictionnaire. Le dictionnaire résultant de la chaîne est donnée dans la figure suivante. On ne s'intéresse pas pour l'instant à la façon dont il est construit mais seulement à sa forme. Sont considérées comme faisant implicitement partie du dictionnaire les motifs unitaires : les octets dont l'adresse correspond aux codes ascii de 0 à 255. Au-delà de 255 commencent les motifs complexes qui sont les séquences originales rencontrées dans le texte. On y retrouve notamment "AI" présent deux fois dans le texte.
Exemple... .
Exemple... Intéressons nous maintenant à la construction du dictionnaire et à la création du fichier compacté. Cette construction est résumée dans la figure suivante ci-dessous. On y précise chronologiquement dans quatre colonnes différentes : les octets lus séquentiellement dans le fichier original : il sont lus les uns après les autres. Les adresses émises dans le fichiers compacté : leur concaténation forme le fichier compacté. Les adresses correspondent aux séquences écrites dans le dictionnaire. On trouve les adresses sous forme décimale et binaire pour constater les variations de taille des motifs. La chaîne tampon qui permet de mémoriser les chaînes rencontrées dans le texte et d'apprendre de nouveaux motifs. Le dictionnaire : on y trouve les ajouts séquentiels qui surviennent à chaque nouveau motif rencontré.
Exemple... .
Exemple... Les premières étapes du compactage sont les suivantes : le premier octet lu est "A". l'algorithme n'effectue que cette action à la première étape."A" est mémorisé dans un tampon T. Puis l'octet "I" est lu. On le place dans le tampon T qui contient alors "AI". On regarde si la chaîne de T existe dans le dictionnaire. Elle n'existe pas, donc on ajoute la chaîne de T ("AI") dans le dictionnaire et on émet le code de "A" a défaut d'une chaîne plus longue. Ensuite on retire "A" de T et on recommence le processus. Si la chaîne dans T existe dans le dictionnaire, on n'émet rien dans le fichier de sortie mais on lit le caractère suivant pour rechercher une chaîne plus longue. C'est ce qui se passe à l'étape 12 dans la figure précédente : "E blanc" est déjà dans le dictionnaire, on tente de chercher "E blanc C" à l'étape suivante. La recherche de "E blanc C" échoue et: on émet le code de "E blanc" puis on garde seulement "C" dans T (le dernier caractère lu): On se retrouve comme en phase d'initialisation.
Exemple... Le processus complet est décrit dans la figure précédente. On peut remarquer qu'à l'étape 12, au lieu de ne rien faire on a émis un code "SP" = 11111111. Ce code signifie qu'à partir de ce point les adresses ne seront plus émises sur 8 bits mais sur 9 bits, ceci pour permettre de gérer des adresses de tailles variables. On tombe ici sur une caractéristique importante de l'algorithme LZW : le code "SP" est inutile au compacteur mais est par indispensable au décompacteur pour décoder les adresses. C'est que l'algorithme de compactage et de décompactage communiquent, l'un donnant à l'autre les informations dont il a besoin. Ce système est l'origine de très nombreuses variantes. Lors de la décompression le dictionnaire est reformé au fur et à mesure selon le même principe que la compression. Lorsque l'algorithme rencontre une adresse supérieure à 255, celle-ci est obligatoirement déjà présente dans le dictionnaire ce qui assure du bon fonctionnement de l'algorithme.
Remarques... L'existence du code "SP" est problématique : on ne peut à priori émettre le code ascii 255. Il s'agit encore ici que compacteur et décompacteur se mette d'accord sur un protocole. L'émission du code ascii 255 peut se faire en deux temps : d'abord "SP"=11111111 (8 bits), puis 011111111 (ascii 255 sur 9 bits). Cette solution n'est pas unique. Le code "SP" peut ne pas être le seul code de communication avec l'algorithme de décompression. D'autres codes peuvent par exemple servir à vider des dictionnaires périodiquement, à créer d'autres dictionnaires : il n'y a pas de limites. On peut remarquer que l'algorithme n'a pas repéré la redondance de "AIDE" présent deux fois dans le fichier. C'est que l'algorithme présenté est une version qui lit le fichier à compresser octet par octet. On peut faire lire plusieurs octets du fichier pour y déceler des redondances d'ordre supérieur et ainsi détecter des chaînes plus longues. On explicite ci-dessous dans les deux figures suivantes une variante de LZW à buffer qui permet ces détections.
Remarques... Dans la deuxième figures des figures suivantes on considère les séquences émises dans le fichier compressée, la nature de l'émission (adresse ou position). La position est un couple (position, longueur) : position du motif émis dans le buffer, et longueur du motif. L'état du buffer est donné dans la figure suivante. On peut y lire les positions et longueurs des éléments redondants.
Remarques... Le motif "AIDE" est détecté à la position 0 du buffer circulaire et réémis dans le fichier sous forme de couple (position, longueur). On peut aussi choisir de le mettre dans le dictionnaire pour une utilisation future. La taille courante d'un tel buffer est de l'ordre de 8 Ko. Il augmente grandement les capacités de l'algorithme.
Remarques... .
spécificité de l’algorithme... Tentons de résumer les spécificités importantes de LZW : Compactage au vol en un seul passage. Dictionnaire non stocké. Algorithme d'apprentissage. Possibilités d'implanter des protocoles entre compacteur et décompacteur. Cependant cette richesse fonctionnelle va de paire avec des problèmes de programmation tout aussi spécifique : pour être efficace les routines complexes de recherches, de détection doivent être écrites dans un langage permettant toutes les optimisations possibles. D'autre part, pour être capable de gérer des messages de longueurs quelconques, des buffers circulaires, le programmeur doit mettre en place un système d'allocation dynamique de mémoire.
L’algorithme LZW (codage fixe)... Supposons que nous disposions d'un dictionnaire initial composé de 256 caractères correspondant à la table ASCII, le rang des caractères est compris entre 0 et 255; si l'on cherche 'Z' dans le dictionnaire, on aura le rang 90. Ajoutant à ces 256 codes deux autres codes possédant les rangs 256 et 257 et servant de codes de contrôle comme nous le verrons plus tard. Le principe est fondé sur le fait qu'une séquence de caractères peut apparaître plusieurs fois dans un fichier. L'intérêt de cette méthode réside dans le fait qu'un indice est transféré sur 12 bits (codage fixe) avec un dictionnaire contenant 4096 emplacements (séquence différentes). Sinon le transfert de la moindre petite séquence de 2 caractères se ferait sur 16 bits; on gagne 4 bits à chaque séquence connue. Lors de la décompression d'un fichier ne contenant que des indices, il faut être capable de réorganiser le dictionnaire sans pour autant le transmettre, comme avec les méthodes de Huffman ou de Fano-Shannon.
Compression... Prenons la séquence ‘EEEE’. A la première itération, le 'E' est chargé dans le code latent; puis à l'aide du deuxième 'E', on va former la chaîne 'EE' qui sera inconnue donc ajoutée au dictionnaire (rang 258). Le deuxième 'E' va passer dans le code latent tandis que le rang du premier est envoyé sur fichier. A la troisième étape, le deuxième et le troisième 'E' forment à nouveau une chaîne 'EE'; cette fois, elle se trouve dans le dictionnaire, donc on ne transmet rien, mais le rang de cette chaîne (258) est sauvegardé pour être envoyé à la prochaine itération. A la quatrième itération, on forme une chaîne 'EEE' qui, inconnue au dictionnaire, est ajouté au rang 259; l'ancien rang est transmis tandis que le dernier 'E' passe dans le code latent. Soit la chaîne transmise : 'E 258 E'.
Compression... /* --- initialisation --- */ DICO = table ASCII /* dictionnaire dynamique */ LATENT = "" MAXDIM = 1024 /* taille maxi du dictionnaire */ NBCAR = 257 /* nbre de caractère courant dans le dico */ /* --- boucle de traitement --- */ LIRE(C) /* lecture du premier caractère */ tant que C<> EOF faire /* test de fin de caractères */ si LATENT = "" alors LATENT = C ANCRANG = ASCII(C) /* sauve le rang de C */ sinon CHAINE = LATENT + C /* concaténation */ /* recherche dichotomique ou dictionnaire utilisant le hash coding, renvoie le rang ou devrait se trouver la chaîne */ TROUVE = RECHERCHE(CHAINE, DICO, RANG) si TROUVE alors LATENT = CHAINE ANCRANG = RANG sinon EMETTRE(ANCRANG) AJOUTER(CHAINE, DICO, RANG) NBCAR = NBCAR + 1 si NBCAR = MAXDIM alors EMETTRE(257) /* remise à zéro di dico */ NBCAR = 257 fin si LATENT = C ANCRANG = ASCII(C) fin si fin si LIRE(C) /* lecture du caractère courant */ fin tant que EMETTRE(ANCRANG, 256) /* indice dernière chaîne */ .
Décompression... . /* --- initialisation --- */ DICO = table ASCII /* ensemble de chaîne construites */ LATENT = "" FININFO = 256 /* code indiquant la fin de compression */ /* --- boucle de traitement --- */ RECEVOIR(CODE) tant que CODE <> FININFO faire si LATENT = "" alors LATENT = CODE ECRIRE(CODE) sinon si CODE < 257 alors /* évaluation d'un chaîne qui ne figure pas dans le dictionnaire */ ECRIRE(CODE) CHAINE = LATENT + CODE AJOUTER(CHAINE, DICO) LATENT = CODE sinon CHAINE = RECHERCHERBIS(CODE, DICO) ECRIRE(CHAINE) TEMPO = LATENT + CHAINE[1] AJOUTER(TEMPO, DICO) LATENT = CHAINE fin si fin si RECEVOIR(CODE) fin tant que
Limites et améliorations... Lorsqu'on exécute le programme de compression, on note une certaine lenteur; ceci est dû en particulier au dictionnaire utilisé. En effet, un stockage dans une table permet de gérer au mieux la place disponible, mais la recherche d'une information oblige à lire toutes les données précédentes. Cette méthode de base est loin d'être efficace en temps d'exécution mais reste pédagogique. Pour pallier le problème de vitesse, nous proposons une gestion du dictionnaire par table de hachage. Le principe d'une table utilisant un accès par hachage consiste à calculer un indice dans la table en fonction de la chaîne à chercher, ce qui nécessite une fonction de hachage. Cette fonction judicieusement élaborée permet d'atteindre de très bonne performances.
Utilisation des algorithmes de compression...(LINUX) Il existe plusieurs programmes de compression sous Unix : zip, pkzip, compress, gzip ... gzip est le plus utilisé actuellement, et sans doute le plus performant. complété par tar, il permet de compresser des dossiers contenant éventuellement une arborescence. On trouvera ci-après une traduction ( très partielle ! ) des pages man de ces commandes. gzip :gzip réduit la taille des fichiers en utilisant un code Lempel-Ziv. Quand c'est possible, chaque fichier est remplacé par un fichier d'extension .gz. gzip ignore les liens symboliques. Usage : gzip [-acdfhlLnNrtvV19] [-S suffix] [name] -d : décompresse ; -h : aide ; -l : liste des fichiers compressés ; -t : teste l'integrité des fichiers ; -1 : compresse plus vite ; -9 : compresse mieux.
. tar :tar sauvegarde plusieurs fichiers ou une archive sur disque et peut restaurer individuellement des fichiers d'une archive. Usage : tar [OPTION]... [FICHIER]... Par exemple tar -cf archive.tar foo bar crée archive.tar à partir des fichiers foo et bar ; tar -tvf archive.tar liste tous les fichiers de archive.tar verbeusement ; tar -xf archive.tar extrait tous les fichiers de archive.tar. Mode principal d'exécution : -t, -list : afficher le contenu d'une archive -x, -extract, -get : extraire les fichiers d'une archive -c, -create : créer une archive -d, -diff, -compare : comparer le contenu de l'archive et le système de fichier -r, -append : accoller les fichiers à la fin de l'archive -u, -update : accoller seulement les nouveaux fichiers et ensuite les copier dans l'archive -A, -catenate : accoller les fichiers «tar» à l'archive -concatenat : identique à -A
. Gnozip L'avantage de ces programmes est qu'ils gèrent généralement plusieurs formats de compression.
Utilisation des algorithmes de compression...(Windows) Power Archive...
Utilisation des algorithmes de compression...(Windows) Winzip: Demo dans la salle...
Utilisation des algorithmes de compression...(Windows)
Résumé... . . Compression Décompression Compactage (Sans perte ou non-destructive) Compression (Avec perte ou destructive) Canonique Statistique Dictionnaire * Suppression d’espace * RLC (ou RLE) * Topologique * Relatif * Huffman * Shanon-Fado * LZW (Code fixe) * LZW (Code variable) Son Image Vidéo * PASC * JPEG * MPEG
La compression dédiée, avec perte... On a vu les performances que l'on était en droit d'attendre des algorithmes de compactage (compression sans perte) : les taux de compression vont jusqu'à 25 % pour des données de type texte. Ce gain est appréciable pour des données de ce type mais pas décisif dans le domaine des transports et du stockage tant les capacités actuelles des disques et des mémoires sont importantes. Il en va tout autrement en ce qui concerne les signaux très volumineux que sont l'image et le son, et plus encore pour ce qui est de la vidéo. En effet la télévision numérique impose aux réseaux qui la véhiculent des débits énormes de l'ordre de 250 Mbits/s. Ici la compression n'est plus facteur d'économie: Elle est indispensable. Les techniques de compression à utiliser sont bien différentes de celles utilisées pour le compactage (compression de texte) et se basent toutes sur le principe suivant : les signaux audio, image et vidéo contiennent une part importante de données que l’œil et l'oreille ne peuvent pas percevoir. Il s'agit donc d'éliminer les données non pertinentes pour ne transmettre que ce qui est perceptible. On parle de compression avec pertes.
La compression dédiée, avec perte... Pour peu que l'information restante soit redondante (ce qui est le cas pour les images et la vidéo), la compression deviendra alors très efficace. On pourra même mesurer et modifier la qualité des signaux distillés. Ces techniques parviennent à des taux de compression très important sans perte de qualité. Elles se basent sur des études précises de l’œil et de l'oreille humaine. Les techniques de compression avec perte sont nombreuses : on citera la plupart sans être exhaustif, du fait que beaucoup s'inspirent des algorithmes de compactage (compression sans perte) déjà étudié. L'étude de ces techniques se décomposera en trois parties: le son, l'image, la vidéo. Dans chacun de ces trois domaines on présentera plus en détail les normes importantes : PASC pour le son, JPEG pour les images fixes et MPEG pour les images animées (Vidéo).
Le son... La compression du son n'est pas à proprement parler une nécessité tant au niveau du stockage qu'au niveau du transport : il existe un ordre de grandeur entre le traitement du son et le traitement de la vidéo. En fait une heure de son de qualité CD (échantillonné sur 16 bits à 44 KHz) occupe "seulement" 723,6 Mo. Cependant la compression du son est un bon exemple de l'approche à adopter quand on étudie une grandeur physique : Étude précise du phénomène. Ces études ont été réalisées très tôt par les opérateurs télécom, soucieux de la qualités des services offerts, et ont été utilisées lors de l'élaboration des techniques de compression. Trouver des solutions souvent liées au traitement du signal pour améliorer la qualité de la compression. Cet aspect est très important pour le son considéré la très grande dispersion du signal : on le constate sur la représentation en fréquence de la figure suivante. Le signal est tellement dispersé que les algorithme de compactage sont complètement inefficaces.
Le son... L'algorithme de compression PASC (Precision Adaptative Sub-band Coding) est à cet égard un exemple facile à appréhender et très didactique : il prend en compte les spécificités du signal et adopte son codage.
Le son... L’étude du phénomène: Le son peut se représenter selon deux grandeurs physiques différentes : La pression. La fréquence. C'est cette dernière qui est choisie pour l'étude, la pression étant trop peu détectable. Comme le montre la figure précédente, le signal sonore est très dispersé : il en ressort que tout seuillage simple sur la courbe entraînerait une perte de qualité dramatique. C'est pour éviter cette perte de qualité que l'on se réfère à la courbe de réponse fréquentielle de l'oreille interne. Cette courbe est donnée dans la figure suivante. On y constate que l'oreille n'est sensible qu'à des fréquences comprises entre 15 Hz et 20 Khz, et ce de manière très inégale. Il s'agit d'utiliser cette courbe pour éliminer toute information superflue.
Le son... C'est sur cette courbe que se base l'algorithme de compression PASC.
Le son... L'algorithme PASC effectue deux tâches distinctes : un rôle filtreur : éliminer du signal toutes les fréquences inférieures à 15 Hz et supérieures à 20 KHz (fréquence inaudibles). un rôle échantilloneur : on divise le spectre audible en 32 bandes de 720 Hz chacune. On compare la valeur moyenne de chaque bande à la valeur correspondant sur la courbe de réponse de l'oreille (voir figure précédente). Toute bande en dessous de la courbe de réponse est éliminée. Chaque bande retenue est divisée en 12 sous-bandes échantillonnées sur 16 bits. On compare encore une fois la valeur des sous-bandes à la courbe de référence. On quantifie les différences à la courbes, et on code ces différences sur un nombre minimum de bits.
Le son... Ces opérations sont renouvelées tous les 8 millièmes de seconde. L'algorithme PASC est résumé sur la figure suivante.
Le son... Cette technique est illustrée par l'exemple de la figure suivante. On y trouve 6 bandes sous forme de traits verticaux qui traversent ou non la zone de masquage (qui est la courbe de référence). Sur les 6 bandes, 2 restent sous les courbes : Elles sont donc rejetées. Les 4 autres sont échantillonnées en 12 autres sous-bandes. Le nombre de bits à coté de chaque sous-bande indique sur combien de bits sera codé l'échantillon. Attendu que c'est une différence à la courbe de référence, le nombre de bits est fonction croissante de l'amplitude de la différence. On remarque que la courbe de masquage est légèrement différente de la courbe de réponse de l'oreille : ces exceptions permettent de rendre mieux audibles certaines superpositions de sons.
Le son... L'algorithme PASC atteint des taux de compression de 25 % ce qui remarquable sur des données aussi dispersées. De plus son rôle filtreur élimine tout ou partie des bruits résiduels.
L’image... Contrairement au son, l'image est un signal très fortement corrélé, comme en atteste la figure suivante où on représente une coupe longitudinale d'un nez de mandrille. Le signal représenté est l'intensité lumineuse sur l'image. Le signal est bien corrélé en dépis du fait que l'image soit assez chahutée.
L’image... Il en découle que les algorithmes classiques tels que Huffmzan, LZW et même le rudimantaire RLC donne de très bon résultats sur les images. Les taux de compression peuvent monter jusqu'à 80 %. Des formats classiques sont basés sur ces algorithmes. Certains sont résumés dans la figure suivante. La compression par plans images consiste à diviser l'image en plusieurs niveaux. Par exemple une image sur 24 bits peut être diviser en 3 niveaux de 8 bits chacun. Les bits de poids forts sont souvent peu corrélés et la compression par huffman ou LZW est très efficace. Les bits de poids faibles sont eux très dispersées, la compression est moins efficace. La compression par prédiction erreur consiste à prévoir la couleur d'un pixel par déduction de la couleur des bits voisins. On peut choisir des méthodes plus ou moins complexes. Ce sont des méthodes probabilistes. Pour avoir une compression sans perte on indique si nécessaire l'erreur à la prédiction.
L’image... .
L’image... Toutes les méthodes citées jusqu'alors sont des méthodes de compression sans perte. Les méthodes de conversion avec pertes sont très nombreuses. On en cite quelques-unes dans la figure suivante qui sont soit statistiques, soit liées à des notions de traitement du signal.
L’image... Le seuillage d'une image consiste à supprimer certaines fréquences. Les problèmes sont les mêmes que pour le son. La qualité est médiocre. La conservation de paramètres statistiques locaux est liée aux méthodes de prédiction: on ne garde que quelques points et on extrapole les points manquants, mais ici sans donner d'information sur les éventuelles distorsion par rapport à l'original. Ces méthodes atténuent les contrastes. Les transformation par matrices de Hadamard consistent à changer de système de coordonnées : on passe du système rouge-vert-bleu au système intensité-luminance-chrominance dans lequelle les corrélations sont plus marquées. Ce système est à l'origine du projet CLAYDN de MATRA qui permet une diffusion de télévision numérique sur des lignes à 20 Mbits/s. Les transformées de cosinus discrets (TDC) sont à la base de la norme JPEG qui est devenu le standard pour la compression des images avec perte. La TCD a pour propriété importante de niveler toute information non pertinente. Ainsi tout bruit ou distorsion provenant de fréquences parasite sera éliminée. On ne va pas présenter la technique TDC dans cette partie. Dans ce qui suit, on va donner un aperçu sur la norme JPEG.
La norme JPEG... La norme JPEG (pour Joint Picture Expert Group) est une norme de compression des images avec perte. Elle utilise un protocole de codage en trois étape : Calcul de la Transformée de Cosinus Discrète : on calcule les coefficients de la TCD sur des blocs de 8x8 pixels. Les coefficients ainsi calculés sont débarrassés du bruit. Seule l'information pertinente est gardée. Une étape de Quantification : L'étape de quantification permet de choisir quels coefficients de la TCD doivent être pris en compte. En effet la TCD réduit largement les bruits mais des valeurs quasiment nulles demeurent dans les matrices de coefficients. On les élimine. Une compression statistique dynamique adaptative. : Les blocs de coefficients quantifiés sont compressés par un algorithme de Huffman sur la base de tables de codage pré-déterminées. L'algorithme est dit dynamique adaptatif car il apprend les motifs très redondants et change sa table de codage en conséquence. Il influence aussi le quantificateur pour éventuellement ne pas supprimer une information, ou limiter la quantification si les contrastes sont gommés.
La norme JPEG... L'architecture de JPEG est résumée dans la figure suivante. L'algorithme atteint des taux de compression de 10 à 16 selon les cas. JPEG est la base de la norme M-JPEG qui permet de visualiser des images animées. Cependant cette norme est insuffisante pour permettre une transmission d'images animées : le débit est très peu constant et assez élevé. Il est par contre très utilisé pour le montage numérique.
La norme JPEG... Exemple:
Le vidéo... Les Normes de Compression La compression de vidéo se base sur le principe de compression d’image et du son (car un vidéo n’est qu’une séquence d’image accompagnée d’une bande sonore). Dans cette section, on va donner une brève idée sur la norme de compression la plus utilisée dans le cas de données vidéo, c’est la norme MPEG.
Le vidéo... Les Normes MPEG · MPEG est le surnom donné au groupe de travail de l'ISO chargé de définir une norme de compression de séquences vidéo (Définition exacte : d'une succession d'images dans le temps accompagnée d'une bande sonore). · En réalité MPEG signifie Moving Pictures Expert Group dont le nom ISO est ISO/IEC JTC1 SC29 WG11 *Signification de ce sigle : -ISO : International Organization for Standardisation -IEC : International Electro-Technical Commission -JTC1 : Joint Technical Committee 1 -SC29 : Sub-Committee 29 -WG11 : Worg Group11 (Moving Pictures with Audio) MPEG définit des méthodes de compression, les éditeurs sont libres de les implanter comme bon leur semble pour commercialiser leurs produits.
Le vidéo... Les 3 Constituants MPEG MPEG a 3 constituants : · La première version définitive de MPEG (appelée MPEG phase I (abrégé MPEG1)) définit un flot de bits pour des signaux audio et vidéo compressés de manière optimisée pour être relu à 1.5 Mbps Vidéo : Définition de la méthode de compression des images animées dans le temps (1,15 MBps) Audio : Compression des séquences audio (256 Kbit/s) System :Synchronisation et multiplexage des séquences audio et vidéo.
Le vidéo... Principes de MPEG Vidéo Le grand principe du codage repose sur les redondances qui existent entre les images successives. Une fois les redondances temporelles déterminées, on utilise les DCT (Transformées de Cosinus Disctètes) pour organiser celles-ci. Les transformations discrètes sont effectuées à partir de matrices 8x8 (Les transformées sont quantifiées et donc de nombreux coefficients sont nuls). Les informations obtenues : Coefficients des DCT, vecteur déplacement, et paramètres de quantification sont ensuite compressés grâce à un codage de Huffman. Prédictions Temporelles Il est clair que la plupart des images vidéo d'une même séquence contiennent de nombreuses redondances. Cependant, le codage d'une image ne dépend pas uniquement de l'image précédente.
Le vidéo... Les évolutions de MPEG MPEG 3 : Une norme obsolète L'objectif était de définir une norme pour la télévision Haute Définition avec des dimensions > 1920 x 1080 x 30 Hz avec un débit de 20 à 40 Mbits par seconde. Cependant le désaccord entre européens d'un côté et américains et japonais de l'autre sur la TVHD entraîne la mort de cette norme au profit de MPEG 2. MPEG 2 : Vers la télévision numérique L'objectif de cette norme est d'atteindre la qualité de la télévision numérique professionnelle avec un débit d'environ 4 MBit/s. Avec un débit de 6 Mbit/s, on atteint l'objectif initial. De plus, MPEG 2 sera probablement la norme adoptée pour la télévision numérique. MPEG 4 : Un standard pour la visiophonie ? Travailler à une vitesse lente (4800 -64000 bps) dans une définition faible (176 x144 x 10 Hz) tel est la définition de cette norme qui n'en est qu'a l'ébauche (Fin des travaux : 1997). Le but est son utilisation dans le visiophone sur des lignes téléphoniques analogiques.
La norme JPEG... L’utilisations de MPEG MPEG 1 : Le CD sous toutes ses formes De par sa définition MPEG1 est dédié à ce support. On trouve des films sur Philips CDI, mais aussi bientôt sur CD-ROM MPEG2 : L'ouverture de la télévision numérique MPEG2 est appru à la télévision avec pour fonction l'acheminement des images. Cette technologie permettra de multiplier les canaux de réception pour une chaîne émettant en numérique.
Conclusion... La compression de données permet de diminuer la place occupée par l'information. Bien que certaines données soient difficilement compressibles voir même impossible à comprimer, la majorité des données utilisées quotidiennement se compriment très bien. Certains détracteurs de la compression argumentent en disant qu'elle deviendra inutile lorsque le prix des mémoires (centrales ou disques) auront suffisamment baissé. Cette idée est fausse ! => Les méthodes de compression utilisent du temps de calcul mais on fait des progrès aussi bien dans l'amélioration des performances des microprocesseurs que dans l'amélioration des unités de stockages de données. De plus, les mémoires de masse d'un ordinateur sont très souvent pleines (disque dur souvent rempli à plus de 80%). En revanche, le microprocesseur est sous utilisé : l'ordinateur ne travaille pas la nuit, il travaille peu lorsqu'on fait du traitement de texte ou de l'encodage d'informations,... Il est donc intéressant d'utiliser les moments libres de l'unité de calcul de l'ordinateur pour comprimer des données. L'arrivée des systèmes d'exploitation multi-tâches (Windows, Windows NT, UNIX,...) permet notamment de comprimer des données pendant que l'utilisateur utilise son traitement de texte ou un autre programme.
Codage arithmétique Cet algorithme est similaire à celui de Huffman car il se base sur la méthode statistique. La différence est que cet algorithme ne transforme pas chaque symbole du texte à compresser en une valeur binaire, mais il utilise la probabilité pour chaque symbole pour calculer un ratio final, ce ratio va être ensuite transformé en valeur binaire qui va être stockée dans le fichier compressé. Cet algorithme est basé sur une valeur de probabilité comprise entre 0 et 1. Il nécessite 5 variables : RANGE, LOW, HIGH, LR (Low Range) et HR (High Range).
Exemple de compression et de décompression Soit à compresser la chaîne suivante : ‘ABCBAA’ (6 caractères) On a : p (A) = 3/6 , p (B) = 2/6, p (C) = 1/6 D’où on a: p (A) = 0.5 : Range =[0.0 moins que 0.5] LR = 0.0 HR = 0.5 p (B) = 0.33 : Range =[0.5 moins que 0.83] LR = 0.5 HR = 0.83 p (C) = 0.16: Range =[0.83 moins que 1.0] LR = 0.83 HR = 1.0
Compression Initialiser les variables: LOW = 0, HIGH = 1 et RANGE = [0..1] Itérer les trios instructions suivantes: RANGE = HIGHT (précedent) – LOW (précedent) LOW = LOW (précedent) + (RANGE * LR du symbole courant) HIGH = LOW (précedent) + (RANGE * HR du symbole courant) La valeur retournée est LOW
Compression . Symbole RANGE LOW HIGH Rien 1 A 0.5 B 0.25 0.415 C 0.165 A 0.5 B 0.25 0.415 C 0.165 0.38695 0.02805 0.400975 0.4102315 0.0092565 0.40560325 0.00462825 0.403289125
Décompression Déterminer à quel intervalle appartient la valeur VALUE Calculer la nouvelle valeur de VALUE à l’aide du calcul suivant : RD = HR – LR VALUE = (VALUE-LR) / RD
Décompression . VALUE RANGE Symbole RD 0.400975 0.0 moins que 0.5 A 0.80195 0.5 moins que 0.83 B 0.33 0.915 .83 moins que 1.0 C 0.16 0.53125 0.09469696 0.1893932
LZ78 Cet algorithme est universel, il n’a pas besoin de connaître les statistiques des données à compresser comme c’est le cas avec le codage de Huffman. Ici, la compression s’effectue en une passe et est bien sûr sans perte de données. La compression est réalisée grâce à l’équivalence de chaînes de caractères. Plus exactement, on utilise une "fenêtre" qui est elle-même séparée en deux parties, pour se déplacer dans le texte, qui contient ainsi la portion précédemment codée et une portion de texte qui reste à compresser.
LZ78 L’idée est toute simple: lorsqu'on retrouve une équivalence entre la partie à compresser et la partie déjà lue, au lieu de réécrire l’équivalence, on écrit seulement en sortie le couple (position, longueur) qui indique ou se trouve l’équivalence et sa longueur dans la partie déjà lue. On ajoute alors le caractère non compressé suivant l’équivalence, au couple. En effet, le contexte fait que s’il n’a pas été codé dans l’expression lue, c’est qu’il y a de grandes chances qu’il ne soit pas compressé ensuite. Cela évite ainsi de perdre un temps précieux à chercher une équivalence. Cet algorithme est un algorithme de compression à base de dictionnaire, puisqu’on garde un dictionnaire (la première partie de la fenêtre) et qu’on y fait référence dans le fichier compressé le couple (position, longueur).
Compression Soit le texte à coder " how-much-wood-would-a-woodchuck " en entrée. On choisit une fenêtre de 21 caractères. Cette fenêtre sera donc coupée en deux parties: - La première représentant donc la partie lue qui sera de 16 caractères et La seconde étant alors de 5 caractères représentant le buffer de codage. Pour des raisons de rapidités, nous avancerons déjà la fenêtre sur le texte. Nous prendrons donc au départ : 16 caractères de partie lue 5 caractères de buffer ho w-much-wood-woul d-a-w oodchuck
Compression Nous remarquons que la chaîne ‘d-‘ se retrouve déjà dans la fenêtre de pré-lecture. Elle sera donc codée puis remplacée par son code dans le fichier de sortie. Ce code sera donc le suivant : (6, 2, a): 6 représente la position du début de l’équivalence en partant de la fin de la fenêtre de pré-lecture (partie verte); 2 est la longueur de la chaîne équivalente et ‘a’ est le caractère suivant dans le buffer qui n’a pas pu être compressé. On déplace ensuite la fenêtre de 3 caractères. Ce qui donne alors : how-m uch-wood-would-a -wood chuck
Compression On remarque que toute la chaîne contenue dans buffer à une équivalence dans la fenêtre de pré lecture. On a alors le code suivant qui remplacera la chaîne dans le fichier de sortie: (13, 5, c). Nous voyons ainsi que la longueur maximale de l’équivalence sera donc la taille du buffer. Cela implique aussi que lorsque l’équivalence sera maximale, on devra chercher le caractère suivant qui ne se trouve pas dans ce buffer. On déplace encore la fenêtre de la taille de l’équivalence + 1 et on tombe alors sur le cas suivant: how-much-wo od-would-a-woodc huck
Compression On tombe alors sur le cas où il n’y a pas d’équivalence entre le buffer et la fenêtre de pré-lecture. On remarque alors une des plus grosses faiblesses de cet algorithme: comme il n’y a pas d’équivalence, on code le premier caractère du buffer par le triplet (0,0,h). On décale ensuite la fenêtre d’un caractère. La faiblesse est donc que lorsqu'on ne trouve pas d’équivalence, un caractère prend plus de place qu’un octet. On continue ensuite l’algorithme jusqu’à ce que l’on n’ait plus aucun caractère dans le buffer.
Compression Tant_que (le buffer de lecture n’est pas vide) faire Début Trouver une équivalence entre une chaîne de caractères dans la fenêtre de lecture et le buffer Si (la longueur de la chaîne équivalente > 0) Alors On retourne le triplet (p, t, c) : où p : la position de la chaîne équivalente dans la fenêtre de lecture t: sa taille c: le caractère suivant dans le buffer On décale la fenêtre de la taille t+1 Sinon Renvoyer le triplet (0, 0, c) où c est le premier caractère du buffer On décale la fenêtre d 1 caractère Fin si Fin Tant_que
Compression Le problème est de trouver la plus grande équivalence au plus vite. La méthode brutale, qui consiste à tester une par une les équivalences, n’est pas acceptable. Il est alors recommandé d’utiliser un arbre binaire de recherche pour effectuer les comparaison pour déterminer l’équivalence la plus longue. L’autre inconvénient de LZ77 est qu’il renvoie toujours un triplet (position, longueur, caractère suivant) même si l’équivalence n’est que d’un octet (1 caractère) ou même aucun. Dans ce cas, nous utilisons plus que 8 bits pour coder 1 caractère. C’est alors que LZSS utilise une astuce pour éviter cela. Nous expliciterons cette astuce par la suite dans l’algorithme LZSS.
La décompression Pour décompresser un fichier qui a été compressé avec la méthode LZ77, on utilise un principe tout aussi simple. Au contraire de la compression, la décompression sera très rapide puisque la recherche d’équivalence, phase qui prend le plus de temps dans la compression, n’est pas à faire. Ici, on utilise seulement la fenêtre de pré-lecture et on recherche l’équivalence du mot codé qui vient, que l’on réécrira à la suite.
La décompression On reprend l’exemple que l’on avait précédemment, c'est-à-dire l’expression " how-much-wood-would-a-woodchuck ". On garde alors notre fenêtre de pré-lecture de 16 caractères, on a donc: Et on a dans le fichier à décompresser le mot codé suivant : (6, 2, a) On repère donc dans la chaîne l’équivalence indiquée c'est-à-dire la chaîne de 2 caractères qui se trouve en 6e position en partant de la fin de la fenêtre. Soit ici : ‘d-’.On ajoute donc cette chaîne avec le caractère ‘a’ indiqué à la suite de la fenêtre. ho w-much-wood-woul ho w-much-wood-woul ho w-much-wood-woul d-a
LZSS Après avoir vu et compris le principe de compression LZ77, nous pouvons voir en quoi et pourquoi la compression LZSS est plus avantageuse. Ainsi, il faut se rappeler le gros désavantage de LZ77: même s’il n’y a pas d’équivalence dans le dictionnaire (la fenêtre de pré-lecture), on utilise plus d’un octet pour représenter un seul caractère. LZSS remédie à ce problème en proposant l’utilisation d’un marqueur qui indique si la donnée suivante est un caractère seul (donc non compressé) ou une paire (position, longueur). Ce marqueur doit être codé sur un seul bit pour ne pas prendre plus de place que nécessaire. Il faut aussi souligner que LZSS est aujourd’hui couramment appelé LZ77 puisque l’ancienne version n’est plus utilisée.
Compression La compression LZSS se fait de la même manière que LZ77 excepté le fait qu’on puisse tomber face à deux cas de figure pour le mot codé : - On a un triplet (marqueur, position, longueur) quand on compresse la donnée. - On a juste un couple (marqueur, caractère non compressé) quand on ne compresse pas. Le marqueur est à 1 lorsque la donnée qui suit est la paire (position, longueur), et 0 si on a simplement le caractère non compressé à la suite. On recherche toujours une équivalence entre le buffer et la fenêtre de pré lecture. Ici encore, il vaut mieux que cette recherche soit faite grâce à l’utilisation d’un arbre de recherche, par hachage ou par d’autres méthodes avancées. Reprenons l’exemple du départ pour examiner les différences : ho w-much-wood-woul d-a-w oodchuck
Compression On procède de la même manière: on voit qu’il y a équivalence entre le buffer et la fenêtre de pré-lecture. Le code de la donnée compressée est alors : (1, 6, 2), et on décale alors la fenêtre de 2 caractères. Maintenant, nous ne trouvons pas d’équivalence dans la fenêtre, on a alors le code suivant qui est rajouté au fichier de sortie : (0, a). Il ne faut pas oublier que le marqueur n’est dans tous les cas codés que sur 1 bit et non 1 octet. On décale la fenêtre d’un caractère. On retombe alors sur une équivalence et le code en résultant est: (1, 13, 5), on déplace alors la fenêtre de 5 caractères…. Et ainsi de suite jusqu’à ce qu’il n’y ait plus de caractères en entrée dans le buffer. how- much-wood-would- a-woo dchuck how-m uch-wood-would-a -wood chuck
La fenêtre de lecture Si l’on regarde à nouveau les exemples, nous nous devons détailler la fenêtre de lecture. En effet, dans la pratique, il y a quelques contraintes à suivre. Tout d’abord, il faut savoir que le principe est simple mais sa représentation informatique ne l’est pas forcément. Il faut ainsi regarder en arrière pour les équivalences, c'est-à-dire dans les données qui ont déjà été traitées. La fenêtre n’est donc qu’un buffer qui contient les caractères qui sont avant la position courante dans le fichier. Chaque caractère qui sort non compressé est ajouté à ce buffer mais aussi les caractères qui sont codés. Or, comme on peut le voir, lorsqu'on recherche des équivalences, nous comparons des données qui sont dans la fenêtre de pré-lecture avec les données qui sont à la position courante.
La fenêtre de lecture Nous avons ainsi deux possibilités : 1–On garde un buffer à la position courante dans le fichier et un autre avec la fenêtre de pré lecture. Cette implémentation est possible mais assez lourde à gérer. 2–On a simplement un buffer qui contiendra toutes les données puisque a fenêtre de pré-lecture et les données à la position courante ne sont rien d’autre que le fichier. Nous n’avons ainsi qu’à nous soucier du pointeur qui marquera la position actuelle dans le fichier, la fenêtre de pré lecture se trouvant alors juste avant. C’est cette solution qui est la plus couramment utilisée.
La fenêtre de lecture Il faut aussi prendre en compte la taille de la fenêtre. Il serait possible de prendre tout le début du fichier jusqu’à la position courante, mais il faut penser au travail de recherche de la plus grosse équivalence qui sera de plus en plus long. Il faut aussi prendre en compte tout simplement la taille du codage de la position de l’équivalence. Plus grande est la fenêtre et plus grand risque d’être le nombre de bits utilisés pour coder cette position. Donc, nous devons obligatoirement choisir une taille pour la fenêtre de pré lecture. En général, on utilise 4096 octets (caractères), mais faut aussi savoir que plus la fenêtre est grande, et meilleure sera la compression. Ainsi, si l’on prend une taille de 4096 octets, nous aurons besoin de 12 bits pour coder la position.
Le codage de la longueur Un autre paramètre est à prendre en compte, la longueur du codage de la longueur. Combien doit-on utiliser de bits pour coder la longueur de l’équivalence? En général, une longueur maximale de 32 caractères est suffisante, ce qui représente seulement 5 bits. Il faut aussi tenir compte d’une longueur minimum pour l’équivalence. On a choisit d’utiliser ici 12 bits pour la position et 5 pour la longueur, soit 17 bits en tout. Ainsi, une équivalence devra être d’au moins 3 caractères pour être avantageuse. Parce que si on code une équivalence de 2 caractères, soit 2 octets et qu’on en utilise alors 17 bits pour la position et la longueur, on utilise alors 1 bit de trop. Cela peut paraître peu, mais dans certains cas, cela peut être très néfaste. On peut de plus tirer profit de cet avantage: on n’a pas d’équivalence de 0, 1 ou 2 caractères, donc, en gardant le codage de la longueur sur 5 bits, on peut coder une longueur de 3 à 35 caractères équivalents ! Il suffit de soustraire 3 à la longueur à chaque fois qu’on compresse et d’ajouter 3 quand on décompresse.