Ajouter les statistiques de compression dans compress
This commit is contained in:
		
							parent
							
								
									ec235ddea7
								
							
						
					
					
						commit
						0bddeb367c
					
				|  | @ -11,24 +11,23 @@ | |||
| #include <errno.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * Calculer un tableau de fréquences d'apparition des | ||||
|  * caractères ASCII dans le fichier donné. Le fichier | ||||
|  * donné doit être ouvert au moins en lecture | ||||
|  * Effectuer un comptage des caractères dans le corpus d'entrée. En déduire | ||||
|  * le tableau des fréquences d'apparition des caractères ASCII | ||||
|  * | ||||
|  * (résultat à libérer avec `free`) | ||||
|  */ | ||||
| static double* _createFrequencies(FILE*); | ||||
| static double* _createFrequencies(FILE*, size_t*); | ||||
| 
 | ||||
| /**
 | ||||
|  * Encoder le fichier d'entrée vers le fichier de sortie | ||||
|  * en suivant les étiquettes passées. Les étiquettes | ||||
|  * peuvent être calculées avec labelTree() | ||||
|  */ | ||||
| void _encodeFromTable(char**, FILE*, Buffer*); | ||||
| static void _encodeFromTable(char**, FILE*, WriteBuffer*); | ||||
| 
 | ||||
| double* _createFrequencies(FILE* file) { | ||||
| double* _createFrequencies(FILE* file, size_t* total) { | ||||
|     double* frequencies = malloc(NUM_CHARS * sizeof(*frequencies)); | ||||
|     int totalChars = 0; | ||||
|     *total = 0; | ||||
| 
 | ||||
|     for (size_t i = 0; i < NUM_CHARS; i++) { | ||||
|         frequencies[i] = 0; | ||||
|  | @ -40,18 +39,18 @@ double* _createFrequencies(FILE* file) { | |||
|     while ((current = fgetc(file)) != EOF) { | ||||
|         assert(current >= 0 && current < NUM_CHARS); | ||||
|         frequencies[current]++; | ||||
|         totalChars++; | ||||
|         (*total)++; | ||||
|     } | ||||
| 
 | ||||
|     // Conversion des effectifs des caractères en fréquences
 | ||||
|     for (size_t i = 0; i < NUM_CHARS; i++) { | ||||
|         frequencies[i] /= totalChars; | ||||
|         frequencies[i] /= *total; | ||||
|     } | ||||
| 
 | ||||
|     return frequencies; | ||||
| } | ||||
| 
 | ||||
| void _encodeFromTable(char** labels, FILE* source, Buffer* output) { | ||||
| void _encodeFromTable(char** labels, FILE* source, WriteBuffer* output) { | ||||
|     int current; | ||||
| 
 | ||||
|     // Lecture du fichier d'entrée caractère par caractère
 | ||||
|  | @ -63,25 +62,26 @@ void _encodeFromTable(char** labels, FILE* source, Buffer* output) { | |||
|         // Ajout du label dans le buffer, caractère par caractère
 | ||||
|         // vidant progressivement le buffer
 | ||||
|         while (*label != '\0') { | ||||
|             pushToBuffer(*label == '1', output); | ||||
|             putBuffer(*label == '1', output); | ||||
|             label++; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void compress(FILE* source, FILE* dest) { | ||||
|     // FIXME: gérer le fichier vide
 | ||||
|     // FIXME: gérer les fichiers ne contenant qu'un seul type de caractère
 | ||||
|     // FIXME: gérer l'entrée depuis stdin (pas de double lecture)
 | ||||
| 
 | ||||
|     // Calcul de la clef de codage à partir de la source
 | ||||
|     // Étape 1 : calcul des fréquences de chaque caractère
 | ||||
|     // FIXME: éviter la division par zéro pour les fichiers vides
 | ||||
|     printVerbose("Calcul des fréquences d'apparition des caractères.\n"); | ||||
|     double* frequencies = _createFrequencies(source); | ||||
|     size_t start_bytes = 0; | ||||
|     double* frequencies = _createFrequencies(source, &start_bytes); | ||||
| 
 | ||||
|     if (isVerbose()) { | ||||
|         printFrequenciesTable(frequencies, NUM_CHARS); | ||||
|     } | ||||
| 
 | ||||
|     // Étape 2 : construction d'un arbre de Huffman pour les fréquences
 | ||||
|     // FIXME: éviter les arbres malformés avec les fichiers ne contenant qu'un
 | ||||
|     // seul type de caractère
 | ||||
|     printVerbose("\nConstruction de l'arbre de Huffman.\n"); | ||||
|     HufTree tree = createTree(frequencies); | ||||
| 
 | ||||
|  | @ -92,6 +92,7 @@ void compress(FILE* source, FILE* dest) { | |||
|         printTree(tree); | ||||
|     } | ||||
| 
 | ||||
|     // Étape 3 : calcul de la clef de codage (coloration de l'arbre)
 | ||||
|     printVerbose("\nÉtiquetage des feuilles de l'arbre.\n"); | ||||
|     char** labels = createTreeLabels(tree); | ||||
| 
 | ||||
|  | @ -99,18 +100,31 @@ void compress(FILE* source, FILE* dest) { | |||
|         printLabelsTable(labels, NUM_CHARS); | ||||
|     } | ||||
| 
 | ||||
|     // Écriture des données compressées vers la sortie
 | ||||
|     Buffer output = createBuffer(dest); | ||||
|     // Étape 4 : écriture des données compressées vers la sortie
 | ||||
|     WriteBuffer output = createWriteBuffer(dest); | ||||
|     printVerbose("\nÉcriture des données compressées.\n"); | ||||
| 
 | ||||
|     printVerbose("\nÉcriture de l'arbre dans la sortie.\n"); | ||||
|     // - Entier : nombre d'octets dans le fichier originel
 | ||||
|     fwrite(&start_bytes, sizeof(start_bytes), 1, dest); | ||||
| 
 | ||||
|     // - Arbre linéarisé : arbre de Huffman permettant le calcul de la clef
 | ||||
|     writeTree(tree, &output); | ||||
| 
 | ||||
|     printVerbose("Écriture des données compressées du fichier.\n"); | ||||
|     // - Données compressées brutes (caractères originels traduits dans
 | ||||
|     //   la clef de codage calculée avant)
 | ||||
|     rewind(source); | ||||
|     _encodeFromTable(labels, source, &output); | ||||
| 
 | ||||
|     // Vidage du dernier octet du tampon et nettoyage
 | ||||
|     flushBuffer(&output); | ||||
| 
 | ||||
|     // Affichage des statistiques de compression
 | ||||
|     size_t end_bytes = sizeof(start_bytes) + getFlushedCount(&output); | ||||
|     double gain = (start_bytes - end_bytes) / (double) start_bytes * 100; | ||||
| 
 | ||||
|     printVerbose("Taille originelle : %d octets.\n", start_bytes); | ||||
|     printVerbose("Taille compressée : %d octets.\n", end_bytes); | ||||
|     printVerbose("Gain : %.2f %% !\n", gain); | ||||
| 
 | ||||
|     // Nettoyage des objets
 | ||||
|     freeTree(tree); | ||||
|     freeTreeLabels(labels); | ||||
|     labels = NULL; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue