/** * \file uncompress.c * \brief Décompression de fichiers * * Ce fichier contient l’implémentation des fonctions nécessaires à la * décompression d’un fichier en `.su` généré par ce programme vers un fichier * en `.ppm` identique à l’original. * */ #include "uncompress.h" /** * Lit le nombre de segments en `uint32_t` contenus dans la zone compressée, * puis pour chaque \ref Segment ajoute ses données décompressées au tableau * dynamique de \p t_zone. * * \param[in] t_file Fichier d’entrée contenant les segments à lire * \param[out] t_zone La zone dans laquelle stocker les \ref Segment */ void read_segments(FILE *t_file, Zone *t_zone) { uint64_t nb_segments, i; Segment *segment; fread(&nb_segments, sizeof(nb_segments), 1, t_file); for(i = 0; i < nb_segments; ++i) { segment = newSegment(0, 0); fread(&segment->left_limit, sizeof(Segment), 1, t_file); darrayPushBack(t_zone->segments, segment); } } /** * Lit les données compressées du fichier d’entrée, tout d’abord le nombre de * zones dans un `uint42_t`, puis pour chaque zone lit les segments. Une fois * une zone lue, elle est ajoutée à \p t_zones. * * \param[in] t_file Fichier d’entrée contenant les données compressées * \param[out] t_zones Tableau dynamique contenant les zones lues */ void read_compressed_zones(FILE *t_file, darray *t_zones) { uint64_t nb_zones, i; Zone *zone; /* read number of zones */ fread(&nb_zones, sizeof(nb_zones), 1, t_file); for(i = 0; i < nb_zones; ++i) { zone = newZone(0, 0, 0); /* read RGB into the zone */ fread(&zone->red, sizeof(zone->red), 3, t_file); /* read each segments of the zone and add them to their vector */ read_segments(t_file, zone); /* add the zone to the zones of the image */ darrayPushBack(t_zones, zone); } } /** * Lit les données basiques du fichier compressé, à savoir la taille en * abscisse et en ordonnée du fichier ppm d’origine et les inscrit dans \p * t_img. * * \param[in] t_file Fichier d’entrée à lire * \param[out] t_img Structure \ref Image stockant les données lues */ void read_compressed_file_meta(FILE *t_file, Image *t_img) { /* read sizeX and sizeY at once */ fread(&t_img->sizeX, sizeof(t_img->sizeX), 2, t_file); } uint8_t *zones_to_data(darray *t_zones, Image *t_img) { uint64_t nb_zones, nb_segments, zoneID, segmentID, k, left_limit, right_limit; uint8_t *data, red, green, blue; Zone *current_zone; Segment *current_segment; data = (uint8_t *)malloc(sizeof(uint8_t) * t_img->sizeX * t_img->sizeY * 3); nb_zones = darraySize(t_zones); for (zoneID = 0; zoneID < nb_zones; ++zoneID) { current_zone = darrayGet(t_zones, zoneID); red = current_zone->red; green = current_zone->green; blue = current_zone->blue; nb_segments = darraySize(current_zone->segments); for (segmentID = 0; segmentID < nb_segments; ++segmentID) { current_segment = darrayGet(current_zone->segments, segmentID); left_limit = current_segment->left_limit; right_limit = current_segment->right_limit; for (k = left_limit; k < right_limit; ++k) { data[k * 3] = red; data[k * 3 + 1] = green; data[k * 3 + 2] = blue; } } } return data; } /** * Décompresse le fichier d’entrée et écrit son équivalent décompressé au * format ppm dans le fichier de sortie. * * \param[in] t_input_file Nom/chemin du fichier d’entrée * \param[in] t_output_file Nom/chemin du fichier de sortie */ void uncompress(const char *t_input_file, const char *t_output_file) { Image *img; darray *zones = darrayNew(sizeof(Zone)); uint8_t *data; FILE *input_file; uint64_t i; if (!t_output_file) { t_output_file = DEFAULT_UNCOMPRESSED_FILE; } img = newImage(); input_file = get_file(t_input_file, "rb"); read_compressed_file_meta(input_file, img); read_compressed_zones(input_file, zones); data = zones_to_data(zones, img); imageSavePPM(t_output_file, img, data); fclose(input_file); /* free memory */ for(i = 0; i < darraySize(zones); ++i) { Zone *zone = darrayGet(zones, i); darrayDelete(zone->segments); } darrayDelete(zones); }