surfaces-unies/src/uncompress.c

126 lines
4.2 KiB
C
Raw Normal View History

/**
* \file uncompress.c
* \brief Décompression de fichiers
*
* Ce fichier contient limplémentation des fonctions nécessaires à la
* décompression dun fichier en `.su` généré par ce programme vers un fichier
* en `.ppm` identique à loriginal.
*
*/
#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 dentré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 dentrée, tout dabord 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 dentré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 dorigine et les inscrit dans \p
* t_img.
*
* \param[in] t_file Fichier dentré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 dentrée et écrit son équivalent décompressé au
* format ppm dans le fichier de sortie.
*
* \param[in] t_input_file Nom/chemin du fichier dentré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);
}