130 lines
4.3 KiB
C
130 lines
4.3 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) {
|
||
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, 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, "rb");
|
||
read_compressed_file_meta(input_file, img);
|
||
read_compressed_zones(input_file, zones);
|
||
puts("===== Read compressed data, now converting zones to ppm data =====");
|
||
data = zones_to_data(zones, img);
|
||
puts("===== Data converted, now saving the PPM file =====");
|
||
imageSavePPM(t_output_file, img, data);
|
||
puts("===== Saved output image, freeing up memory =====");
|
||
fclose(input_file);
|
||
/* free memory */
|
||
for(i = 0; i < darraySize(zones); ++i) {
|
||
Zone *zone = darrayGet(zones, i);
|
||
darrayDelete(zone->segments);
|
||
}
|
||
darrayDelete(zones);
|
||
}
|