Compte rendu: Compression/Décompression d une image binaire Sandrine SOUB et Benjamin RAMBAUD 20 décembre 2013 Résumé L objectif de ce Projet est d implémenter sous MATLAB le principe de compression/décompression d une image binaire selon la recommandation T.4 de l ITU-T (RFC 804), c est à dire le principe du facsimilé plus couramment connu sous l acronyme fax. Table des matières 1 Organisation du code 1 2 Compression 2 2.1 Détection des séquences de 0 et de 1 : fonction calcul longueur......... 2 2.2 Codage : fonction codcomplet............................. 2 2.2.1 Lecture dans un fichier texte......................... 2 2.2.2 Codage complet d une ligne.......................... 3 2.3 Écriture dans un fichier : fonction write file..................... 3 3 Décompression 4 3.1 Lecture dans un fichier : fonction read file...................... 4 3.2 Décodage : fonction decod............................... 5 3.3 Reconstruction des séquences de 0 et de 1 : fonction reconstruction...... 6 4 Simulation : fonction faxt4 6 5 Bibliographie 8 1 Organisation du code Comme vu sur la figure 1 suivante, l organisation du projet se fait en deux grandes parties. La première est basée au préalable sur le principe de codage à une dimension ensuite la compression proprement dite avec la méthode d écriture dans un fichier. La seconde traite les notions générales de décompression entre autres la reconstruction effective d une séquence binaire. Et enfin, le processus réalisé sera appliqué à une image binaire monochrome (cf figure 8). 1
Figure 1 Organisation du code. 2 Compression 2.1 Détection des séquences de 0 et de 1 : fonction calcul longueur Figure 2 fonction calcul longueur. A partir d une chaîne de caractères composée de 0 et 1,la fonction calcul longueur permet de connaitre les longueurs des suites de pixels blancs (valeur 1) et noirs (valeur 0) d une ligne de l image. Elle retourne le vecteur contenant ces longueurs. Pour construire cette fonction, il suffit de compter bloc par bloc les occurrences d une suite de pixels tout en s assurant de commencer toujours par compter le nombre de pixels blancs afin de respecter la recommandation T.4. 2.2 Codage : fonction codcomplet Pour effectuer le codage complet d une image, il est nécessaire de savoir comment récupérer à partir d un fichier texte les informations relatives au code et enfin effectuer le codage proprement dit suivant la recommandation T.4. Figure 3 fonction codcomplet. 2.2.1 Lecture dans un fichier texte Le principe du codage de la recommandation T.4 repose sur le codage des longueurs obtenues à l aide de deux dictionnaires, white codes et black codes utilisant un codage de Huffman. 2
Pour lire dans ces fichiers textes comprenant en première colonne la séquence à coder, en deuxième colonne la longueur de cette séquence et en dernière colonne le nombre à coder ; on va créer une fonction nommée lire fichier() qui retournera le contenu des fichiers black codes et white codes. L implémentation de cette fonction se résume en trois parties : Tout d abord on va ouvrir les fichiers à l aide de la fonction fopen. Ensuite en utilisant successivement les fonctions fgetl et sscanf on va récupérer et lire le contenu du fichier choisi, enfin après une conversion adéquate en cell on va ferme le fichier avec fclose. Remarque : Le choix d une conversion en cell vient du fait que nos fichiers ont plusieurs types de caractères or une cell de manipuler au mieux plusieurs types dans une matrice. Ne pas oublier de convertir char(48) en 0 et char(49) en 1. 2.2.2 Codage complet d une ligne Par convention, la séquence est composée de deux informations qui sont le makeup et le terminating. En effet, le makeup correspond aux longueurs de séquences supérieures à 63 et multiples de 64 et le terminating est le reste de la division euclidienne de la longueur du code par 64. Le codage consiste, ligne après ligne, à concaténer les codes binaires correspondant à chaque séquence de pixels, en ajoutant les codes EOL de fin de ligne puis la séquence binaire de fin de document. Pour cela on procèdera comme suit : On récupère le vecteur v des longueurs des suites de pixels blancs(valeur 1) et noirs(valeur 0) d une ligne avec la fonction calcul longueur. En fonction de la place du nombre de redondance d un pixel dans le vecteur v on sait si le pixel en noir ou blanc. En effet, avec la convention de commencer toujours par un pixel blanc on obtient que les positions paires correspondent aux pixels noirs et les impaires aux pixels blancs. Ensuite grâce aux propriétés de makeup et terminating, on décompose la ligne à l aide des fonctions floor pour le makeup et mod pour le terminating. Enfin, on concatène toutes les séquences successives en prenant garde à rajouter à chaque fois le EOL 2.3 Écriture dans un fichier : fonction write file Figure 4 Fonction write file. Elle permet d écrire dans un fichier le code complet généré précédemment. En revanche, nous allons découper le code en groupe de 8 bits puis convertir ces groupes en décimal afin d accroître la qualité de compression de notre code. L implémentation de write file réside en trois grandes étapes : 3
- Création ou ouverture du fichier sur lequel on aimerait écrire la séquence binaire. Si le fichier existe on l ouvre avec fopen sinon on le crée en rajoutant en paramètre de fopen le caractère w +. - Écriture effective de la séquence dans le code avec fwrite en tenant bien compte des différentes conversions nécessaires pour arriver à la forme décimale. Ces conversions sont gérées par les fonctions num2str et bin2dec. - Fermeture du fichier avec fclose et vérification que l écriture s est bien faîte en consultant tout simplement le contenu du fichier considéré au préalable. Remarques : Dans notre code le nombre de bits utilisés pour la conversion est de 8. Si le code binaire complet n est pas multiple de 8, on padde les derniers bits pour attendre un multiple de 8 le plus proche de la longueur du code. Pour accroître davantage la compression, il aurait été possible de convertir les groupes en hexadécimal. D après la convention T.4 le EOF (End Of File) correspond à 7 EOL. 3 Décompression Les opérations effectuées précédemment sur l image pour le codage seront reprises en ordre inverse : 1. Lecture du fichier binaire pour obtenir la suite binaire correspondante 2. Ensuite, décodage de cette suite à l aide de white tree et black tree 3. Enfin, reconstruction de la séquence originelle et donc de l image. 3.1 Lecture dans un fichier : fonction read file Figure 5 Fonction read file. Après l ouverture du fichier à l aide de fopen, il est nécessaire de lire ligne par ligne avec la fonction sscanf puis de convertir les entiers en séquence binaire de 8 bits. Ouverture du fichier Lecture ligne après ligne Conversion des entiers en séquence binaire Stockage dans la variables c read 4
3.2 Décodage : fonction decod Figure 6 Fonction decod. La fonction de décodage est de loin la plus complexe à mettre en oeuvre. En effet, il y a de nombreux paramètres à prendre en compte : La couleur du pixel : 1 pour blanc et 0 pour noir La différenciation entre le Makeup et le terminating La reconnaissance de la fin d une ligne indiquant de recommencer par la lecture d un pixel blanc Gérer l indice des arbres white tree et black tree utilisant Huffman Gérer le déplacement dans la séquence binaire à décoder La reconnaissance du fin de fichier annoncé par 6 EOL à la suite L architecture de la fonction se décompose ainsi en quelques étapes : Tant que l on a pas atteint le EOF Tant que l on a pas atteint le EOL Déterminer la couleur du pixel (on commence par un blanc ) : Tant qu on est dans le cas du Makeup : Le bit lu est 0 : - l indice de l arbre est multiplié par 2 : i tree = 2i tree Le bit lu est 1 : - l indice de l arbre est multiplié par 2 et on lui ajoute 1 : i tree = 2i tree + 1 Si la valeur lu dans l arbre est différente de -1 alors on a trouvé la valeur du Makeup Si la valeur est 8193 alors on a atteint un EOL. Si les 6 autres valeurs à la suite sont aussi 8193 alors on a atteint le EOF Sinon on continue Tant qu on est dans le cas du Terminating : Cela est très similaire au cas Makeup. À défaut qu il n est pas nécessaire de vérifier le EOL ou le EOF. Le traitement pour le cas d un pixel noir est identique à défaut de lire dans l arbre black tree au lieu de lire dans white tree 5
Pour l exemple, décodons la séquence binaire suivante : 00110101 }{{} Makeup 1011 }{{} T erminating } {{ } Blancs 0000110111 }{{} Makeup On commence par un pixel blanc et par le Makeup : 11 }{{} T erminating } {{ } Noirs i tree = 1 et bit lu = 0 i tree = 2 1 = 2 white tree(2) = 1 i tree = 2 et bit lu = 0 i tree = 2 2 = 4 white tree(4) = 1 i tree = 4 et bit lu = 1 i tree = 2 4 + 1 = 9 white tree(9) = 1 i tree = 9 et bit lu = 1 i tree = 2 9 + 1 = 19 white tree(19) = 1 i tree = 19 et bit lu = 0 i tree = 2 19 = 38 white tree(38) = 1 i tree = 38 et bit lu = 1 i tree = 2 38 + 1 = 77 white tree(77) = 1 i tree = 77 et bit lu = 0 i tree = 2 77 = 154 white tree(154) = 1 i tree = 154 et bit lu = 1 i tree = 2 154 + 1 = 309 white tree(309)=0 La longueur est donc 0 pour le Makeup et de la même façon on a 4 pour le terminating. Ainsi, il y a 0+4 pixels blancs. De même pour les pixels noirs : la longueur est de 0 + 2. On retrouve donc comme vecteur des longueurs : [4 2]. 3.3 Reconstruction des séquences de 0 et de 1 : fonction reconstruction Figure 7 Fonction reconstruction. Cette fonction est bien plus simple que celle de décodage. En effet, il suffit de faire attention au EOL, EOF ainsi qu à la bonne couleur. On va effectué un traitement ligne par ligne. C est à dire que l on stocke le vecteur des longueurs pour une ligne puis que l on écrit la suite de 0 et de 1 correspondante. Enfin, on stocke chaque suite dans les lignes de l image estimée img est. Ainsi, on retrouve notre image de départ! 4 Simulation : fonction faxt4 La simulation se fait via la fonction faxt4 qui effectue le traitement établi sur la figure 1 6
Figure 8 Comparaison entre l image originelle et l image reçue. Nous pouvons analyser le résultat de la simulation avec différents critères : Critère subjectif : - On remarque qu il n y pas de différence visible à l œil nu. Critère objectif : - On peut utiliser la fonction isequal de Matlab qui va retourner 1 si la matrice image originelle img et la matrice image reçue img est sont identique et 0 sinon. Il se trouve que isequal(img, img est) retourne la valeur 1. Ainsi notre image reçue est identique à notre image de départ et la chaîne compression/décompression est opérée sans perte. On remarque en revanche que la compression n est absolument pas effectué avec une image originelle de 15.5ko et de 57.9ko après compression. Il semblerait que le problème soit dans la phase d écriture du fichier. En effet, si on utilise la formule suivante : t = 1 On obtient un taux de compression de 56.8%. Cette formule coïncide avec : t = 1 longueur du code hauteur largeur de l image taille de l image compressée taille de l image non compressée 7
5 Bibliographie Taux de compression : http ://w3.u-grenoble3.fr/zampa/cours/fichesl2/compression.pdf http ://fr.wikipedia.org/wiki/taux de compression de donn%c3%a9es 8