Commente l'algorithme de compression dans compress.c
This commit is contained in:
parent
68817286ea
commit
16266d3f9a
|
@ -33,9 +33,9 @@ double* _createFrequencies(FILE* file, size_t* total) {
|
||||||
frequencies[i] = 0;
|
frequencies[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Lecture du fichier caractère par caractère et comptage
|
||||||
int current;
|
int current;
|
||||||
|
|
||||||
// Lecture du fichier caractère par caractère et comptage
|
|
||||||
while ((current = fgetc(file)) != EOF) {
|
while ((current = fgetc(file)) != EOF) {
|
||||||
assert(current >= 0 && current < NUM_CHARS);
|
assert(current >= 0 && current < NUM_CHARS);
|
||||||
frequencies[current]++;
|
frequencies[current]++;
|
||||||
|
@ -69,7 +69,11 @@ void _encodeFromTable(char** labels, FILE* source, WriteBuffer* output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void compress(FILE* source, FILE* dest) {
|
void compress(FILE* source, FILE* dest) {
|
||||||
// Étape 1 : calcul des fréquences de chaque caractère
|
// ÉTAPE 1 : calcul des fréquences d'apparition de chaque caractère
|
||||||
|
// dans le fichier source. Ce programme prend le terme caractère au sens
|
||||||
|
// restreint d'octet. Dans le cas où l'on compresse des fichiers Unicode
|
||||||
|
// utilisant des caractères sur plusieurs octets, on aura donc une
|
||||||
|
// compression moins optimale.
|
||||||
// FIXME: éviter la division par zéro pour les fichiers vides
|
// FIXME: éviter la division par zéro pour les fichiers vides
|
||||||
printVerbose("Calcul des fréquences d'apparition des caractères.\n");
|
printVerbose("Calcul des fréquences d'apparition des caractères.\n");
|
||||||
size_t start_bytes = 0;
|
size_t start_bytes = 0;
|
||||||
|
@ -79,7 +83,8 @@ void compress(FILE* source, FILE* dest) {
|
||||||
printFrequenciesTable(frequencies, NUM_CHARS);
|
printFrequenciesTable(frequencies, NUM_CHARS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Étape 2 : construction d'un arbre de Huffman pour les fréquences
|
// ÉTAPE 2 : construction d'un arbre de Huffman correspondant aux
|
||||||
|
// fréquences d'apparition des caractères
|
||||||
// FIXME: éviter les arbres malformés avec les fichiers ne contenant qu'un
|
// FIXME: éviter les arbres malformés avec les fichiers ne contenant qu'un
|
||||||
// seul type de caractère
|
// seul type de caractère
|
||||||
printVerbose("\nConstruction de l'arbre de Huffman.\n");
|
printVerbose("\nConstruction de l'arbre de Huffman.\n");
|
||||||
|
@ -92,7 +97,9 @@ void compress(FILE* source, FILE* dest) {
|
||||||
printTree(tree);
|
printTree(tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Étape 3 : calcul de la clef de codage (coloration de l'arbre)
|
// ÉTAPE 3 : calcul de la clef de codage en étiquettant les chaque feuille
|
||||||
|
// de l'arbre. Pour chaque sommet traversé, s'il est le fils gauche de son
|
||||||
|
// parent, l'étiquette est augmentée d'un '0', sinon elle l'est d'un '1'
|
||||||
printVerbose("\nÉtiquetage des feuilles de l'arbre.\n");
|
printVerbose("\nÉtiquetage des feuilles de l'arbre.\n");
|
||||||
char** labels = createTreeLabels(tree);
|
char** labels = createTreeLabels(tree);
|
||||||
|
|
||||||
|
@ -100,7 +107,9 @@ void compress(FILE* source, FILE* dest) {
|
||||||
printLabelsTable(labels, NUM_CHARS);
|
printLabelsTable(labels, NUM_CHARS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Étape 4 : écriture des données compressées vers la sortie
|
// ÉTAPE 4 : écriture des données compressées vers la sortie. Les données
|
||||||
|
// écrites permettent de restituer le fichier originel : nombre de
|
||||||
|
// caractères stockés, arbre de Huffman et données compressées brutes
|
||||||
WriteBuffer output = createWriteBuffer(dest);
|
WriteBuffer output = createWriteBuffer(dest);
|
||||||
printVerbose("\nÉcriture des données compressées.\n");
|
printVerbose("\nÉcriture des données compressées.\n");
|
||||||
|
|
||||||
|
@ -116,15 +125,14 @@ void compress(FILE* source, FILE* dest) {
|
||||||
_encodeFromTable(labels, source, &output);
|
_encodeFromTable(labels, source, &output);
|
||||||
flushBuffer(&output);
|
flushBuffer(&output);
|
||||||
|
|
||||||
// Affichage des statistiques de compression
|
// ÉTAPE 5 : affichage des statistiques de compression et fin
|
||||||
size_t end_bytes = sizeof(start_bytes) + getFlushedCount(&output);
|
size_t end_bytes = sizeof(start_bytes) + getFlushedCount(&output);
|
||||||
double gain = (start_bytes - end_bytes) / (double) start_bytes * 100;
|
double gain = ((double) start_bytes - end_bytes) / start_bytes * 100;
|
||||||
|
|
||||||
printVerbose("Taille originelle : %d octets.\n", start_bytes);
|
printVerbose("Taille originelle : %d octets.\n", start_bytes);
|
||||||
printVerbose("Taille compressée : %d octets.\n", end_bytes);
|
printVerbose("Taille compressée : %d octets.\n", end_bytes);
|
||||||
printVerbose("Gain : %.2f %% !\n", gain);
|
printVerbose("Gain : %.2f %% !\n", gain);
|
||||||
|
|
||||||
// Nettoyage des objets
|
|
||||||
freeTree(tree);
|
freeTree(tree);
|
||||||
freeTreeLabels(labels);
|
freeTreeLabels(labels);
|
||||||
labels = NULL;
|
labels = NULL;
|
||||||
|
|
Loading…
Reference in New Issue