128 lines
4.1 KiB
C
128 lines
4.1 KiB
C
|
/**
|
|||
|
* \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) {
|
|||
|
uint32_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->left_limit), 2, 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) {
|
|||
|
uint32_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);
|
|||
|
DEBUG { printf("X: %ld\tY: %ld\n", t_img->sizeX, t_img->sizeY); }
|
|||
|
}
|
|||
|
|
|||
|
uint8_t *zones_to_data(darray *t_zones, Image *t_img) {
|
|||
|
uint64_t nb_zones, nb_segments, i, j, 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->sizeX * 3);
|
|||
|
nb_zones = darraySize(t_zones);
|
|||
|
for(i = 0; i < nb_zones; ++i) {
|
|||
|
current_zone = darrayGet(t_zones, i);
|
|||
|
red = current_zone->red;
|
|||
|
green = current_zone->green;
|
|||
|
blue = current_zone->blue;
|
|||
|
nb_segments = darraySize(current_zone->segments);
|
|||
|
for(j = 0; j < nb_segments; ++j) {
|
|||
|
current_segment = darrayGet(current_zone->segments, j);
|
|||
|
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, "wb");
|
|||
|
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);
|
|||
|
|
|||
|
/* free memory */
|
|||
|
for(i = 0; i < darraySize(zones); ++i) {
|
|||
|
Zone *zone = darrayGet(zones, i);
|
|||
|
darrayDelete(zone->segments);
|
|||
|
}
|
|||
|
darrayDelete(zones);
|
|||
|
}
|