2018-11-26 01:28:15 +00:00
|
|
|
|
/**
|
|
|
|
|
* \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) {
|
2018-11-27 09:38:11 +00:00
|
|
|
|
uint64_t nb_segments, i;
|
2018-11-26 01:28:15 +00:00
|
|
|
|
Segment *segment;
|
|
|
|
|
fread(&nb_segments, sizeof(nb_segments), 1, t_file);
|
|
|
|
|
for(i = 0; i < nb_segments; ++i) {
|
|
|
|
|
segment = newSegment(0, 0);
|
2018-11-27 09:38:11 +00:00
|
|
|
|
fread(&segment->left_limit, sizeof(Segment), 1, t_file);
|
2018-11-26 01:28:15 +00:00
|
|
|
|
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) {
|
2018-11-27 09:38:11 +00:00
|
|
|
|
uint64_t nb_zones, i;
|
2018-11-26 01:28:15 +00:00
|
|
|
|
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) {
|
2018-11-27 11:47:28 +00:00
|
|
|
|
uint64_t nb_zones, nb_segments, zoneID, segmentID, k, left_limit, right_limit;
|
2018-11-26 01:28:15 +00:00
|
|
|
|
uint8_t *data, red, green, blue;
|
|
|
|
|
Zone *current_zone;
|
|
|
|
|
Segment *current_segment;
|
2018-11-27 11:47:28 +00:00
|
|
|
|
data = (uint8_t *)malloc(sizeof(uint8_t) * t_img->sizeX * t_img->sizeY * 3);
|
2018-11-26 01:28:15 +00:00
|
|
|
|
nb_zones = darraySize(t_zones);
|
2018-11-27 11:47:28 +00:00
|
|
|
|
for (zoneID = 0; zoneID < nb_zones; ++zoneID) {
|
|
|
|
|
current_zone = darrayGet(t_zones, zoneID);
|
2018-11-26 01:28:15 +00:00
|
|
|
|
red = current_zone->red;
|
|
|
|
|
green = current_zone->green;
|
|
|
|
|
blue = current_zone->blue;
|
|
|
|
|
nb_segments = darraySize(current_zone->segments);
|
2018-11-27 11:47:28 +00:00
|
|
|
|
for (segmentID = 0; segmentID < nb_segments; ++segmentID) {
|
|
|
|
|
current_segment = darrayGet(current_zone->segments, segmentID);
|
2018-11-26 01:28:15 +00:00
|
|
|
|
left_limit = current_segment->left_limit;
|
|
|
|
|
right_limit = current_segment->right_limit;
|
2018-11-27 11:47:28 +00:00
|
|
|
|
for (k = left_limit; k < right_limit; ++k) {
|
2018-11-26 01:28:15 +00:00
|
|
|
|
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();
|
2018-11-27 09:38:11 +00:00
|
|
|
|
input_file = get_file(t_input_file, "rb");
|
2018-11-26 01:28:15 +00:00
|
|
|
|
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);
|
2018-11-27 09:38:11 +00:00
|
|
|
|
fclose(input_file);
|
2018-11-26 01:28:15 +00:00
|
|
|
|
/* free memory */
|
|
|
|
|
for(i = 0; i < darraySize(zones); ++i) {
|
|
|
|
|
Zone *zone = darrayGet(zones, i);
|
|
|
|
|
darrayDelete(zone->segments);
|
|
|
|
|
}
|
|
|
|
|
darrayDelete(zones);
|
|
|
|
|
}
|