surfaces-unies/src/uncompress.c

126 lines
4.2 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* \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);
}