first steps in uncompressing, will finish later
This commit is contained in:
		
							parent
							
								
									6f5bbedc0d
								
							
						
					
					
						commit
						750a7a750f
					
				
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -13,3 +13,4 @@ clean: | ||||
| 	@rm -rf doc/html | ||||
| 	@rm -rf doc/latex | ||||
| 	@rm -rf gmon.out | ||||
| 	@rm -rf cmake-build-debug | ||||
|  | ||||
| @ -38,7 +38,7 @@ PROJECT_NAME           = "Compression par surfaces unies" | ||||
| # could be handy for archiving the generated documentation or if some version | ||||
| # control system is used. | ||||
| 
 | ||||
| PROJECT_NUMBER         = 0.1 | ||||
| PROJECT_NUMBER         = 0.4 | ||||
| 
 | ||||
| # Using the PROJECT_BRIEF tag one can provide an optional one line description | ||||
| # for a project that appears at the top of each page and should give viewer a | ||||
|  | ||||
| @ -13,9 +13,9 @@ | ||||
|  *  \param[in] t_zone Zone à laquelle le pixel est éligible ou non | ||||
|  *  \return Valeur booléenne, `1` si le pixel est éligible, `0` sinon | ||||
|  */ | ||||
| uint8_t sameColor(Pixel *t_pixel, Zone *t_zone) { | ||||
|   return (t_pixel->r == t_zone->r && t_pixel->g == t_zone->g && | ||||
|           t_pixel->b == t_zone->b) | ||||
| int32_t sameColor(Pixel *t_pixel, Zone *t_zone) { | ||||
|   return (t_pixel->red == t_zone->red && t_pixel->green == t_zone->green && | ||||
|           t_pixel->blue == t_zone->blue) | ||||
|              ? 1 | ||||
|              : 0; | ||||
| } | ||||
| @ -36,9 +36,9 @@ uint8_t sameColor(Pixel *t_pixel, Zone *t_zone) { | ||||
| void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone) { | ||||
|   const size_t img_size = darraySize(t_img->pixels); | ||||
|   Pixel *current_pixel; | ||||
|   const uint32_t y = (uint32_t)(t_idx / t_img->x); | ||||
|   const uint32_t y = (uint32_t)(t_idx / t_img->sizeX); | ||||
|   int64_t left_limit, right_limit; | ||||
|   const int64_t xd_limit = (int64_t)t_img->x * (y + 1); | ||||
|   const int64_t xd_limit = (int64_t)t_img->sizeX * (y + 1); | ||||
| 
 | ||||
|   if (t_idx >= (int64_t)img_size || t_idx < 0) { | ||||
|     return; | ||||
| @ -56,7 +56,7 @@ void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone) { | ||||
|     current_pixel->visited = 1; | ||||
|   } | ||||
| 
 | ||||
|   for (left_limit = t_idx; left_limit - (y - 1) * (int64_t)t_img->x >= 0; | ||||
|   for (left_limit = t_idx; left_limit - (y - 1) * (int64_t)t_img->sizeX >= 0; | ||||
|        --left_limit) { /* fetch right limit of segment */ | ||||
|     current_pixel = darrayGet(t_img->pixels, (size_t)left_limit); | ||||
|     if (current_pixel->visited || !sameColor(current_pixel, t_zone)) { | ||||
| @ -69,7 +69,7 @@ void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone) { | ||||
|                  newSegment((uint32_t)right_limit, (uint32_t)left_limit)); | ||||
|   for (; left_limit <= right_limit; | ||||
|        ++left_limit) { /* process every pixel up and down the segment */ | ||||
|     addPixelToSelectedZone(t_img, t_idx + t_img->x, t_zone); | ||||
|     addPixelToSelectedZone(t_img, t_idx + t_img->sizeX, t_zone); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -105,7 +105,7 @@ void chooseZoneForPixel(Image *t_img, int64_t t_idx, darray *t_zones) { | ||||
|   /* if none of the same color was found, create a new one, add it to the image
 | ||||
|    * and add the selected pixel and its neighbours of the same color to the zone | ||||
|    */ | ||||
|   current_zone = newZone(pixel->r, pixel->g, pixel->b); | ||||
|   current_zone = newZone(pixel->red, pixel->green, pixel->blue); | ||||
|   darrayPushBack(t_zones, current_zone); | ||||
|   addPixelToSelectedZone(t_img, t_idx, current_zone); | ||||
| } | ||||
| @ -127,20 +127,52 @@ darray *imgToZones(Image *t_img) { | ||||
|   return zones; | ||||
| } | ||||
| 
 | ||||
| void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones) { | ||||
|   size_t i, j; | ||||
|   Zone *current_zone; | ||||
| /**
 | ||||
|  *  Cette fonction écrit dans \p t_output la taille en `uint64_t` de la zone, | ||||
|  *  c’est à dire le nombre de segment qu’elle contient, puis écrit | ||||
|  *  individuellement chaque segment dans \p t_output. | ||||
|  * | ||||
|  *  \param[out] t_output Fichier de sortie | ||||
|  *  \param[in] t_segments Segments à écrire dans \p t_output | ||||
|  */ | ||||
| void write_segments(FILE *t_output, darray *t_segments) { | ||||
|   uint64_t nb_segments, j; | ||||
|   Segment *segment; | ||||
|   fwrite(&t_img->x, sizeof(t_img->x), 2, t_output); | ||||
|   for (i = 0; i < darraySize(t_zones); ++i) { | ||||
|     current_zone = darrayGet(t_zones, i); | ||||
|     fwrite(¤t_zone->r, sizeof(current_zone->r) * 3, 1, t_output); | ||||
|     for (j = 0; j < darraySize(current_zone->segments); ++j) { | ||||
|       segment = darrayGet(current_zone->segments, j); | ||||
|   nb_segments = darraySize(t_segments); | ||||
|   fwrite(&nb_segments, sizeof(nb_segments), 1, t_output); | ||||
|   for (j = 0; j < darraySize(t_segments); ++j) { | ||||
|     segment = darrayGet(t_segments, j); | ||||
|     fwrite(&segment->right_limit, sizeof(Segment), 1, t_output); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  \brief function description | ||||
|  * | ||||
|  *  Écrit la taille de l’image en abscisse et ordonnées, les deux sous forme de | ||||
|  *  `uint64_t` puis le nombre de zones sous forme de `uint64_t`. Puis, pour | ||||
|  *  chaque zone son code couleur composé de trois `uint8_t` successifs | ||||
|  *  représentant ses couleurs rouge, vert et bleu sont écrit dans le fichier de | ||||
|  *  sortie \p t_output. Après chaque écriture de zone, l’ensemble des segments | ||||
|  *  de la zone est libéré de la mémoire. Une fois toutes les zones écrites dans | ||||
|  *  le fichier de sortie, \p t_zones et libéré de la mémoire. | ||||
|  * | ||||
|  *  \param[in] t_img \ref Image contenant les dimensions du fichier d’origine | ||||
|  *  \param[out] t_output Fichier où sont écrites les données compressées | ||||
|  *  \param[in] t_zones Tableau des \ref Zone à écrire puis libérer | ||||
|  */ | ||||
| void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones) { | ||||
|   uint64_t i, nb_zones = darraySize(t_zones); | ||||
|   Zone *current_zone; | ||||
|   fwrite(&t_img->sizeX, sizeof(t_img->sizeX), 2, t_output); | ||||
|   fwrite(&nb_zones, sizeof(nb_zones), 1, t_output); | ||||
|   for (i = 0; i < darraySize(t_zones); ++i) { | ||||
|     current_zone = darrayGet(t_zones, i); | ||||
|     fwrite(¤t_zone->red, sizeof(current_zone->red) * 3, 1, t_output); | ||||
|     write_segments(t_output, current_zone->segments); | ||||
|     darrayDelete(current_zone->segments); | ||||
|   } | ||||
|   darrayDelete(t_zones); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| @ -154,12 +186,14 @@ void compress(const char *t_input_file, const char *t_output_file) { | ||||
|   Image *img; | ||||
|   darray *zones; | ||||
|   FILE *output_file; | ||||
|   if (!t_output_file) { | ||||
|     t_output_file = DEFAULT_COMPRESSED_NAME; | ||||
|   } | ||||
|   img = newImage(); | ||||
|   imageLoadPPM(t_input_file, img); | ||||
|   output_file = get_file(t_output_file, "wb"); | ||||
|   zones = imgToZones(img); | ||||
|   write_compressed_file(img, output_file, zones); | ||||
|   deleteImage(img); | ||||
|   darrayDelete(zones); | ||||
|   fclose(output_file); | ||||
| } | ||||
|  | ||||
| @ -8,14 +8,20 @@ | ||||
| 
 | ||||
| #include "ppm.h" | ||||
| 
 | ||||
| #define DEFAULT_COMPRESSED_NAME "output.su" | ||||
| 
 | ||||
| /// Teste l’éligibilité d’un pixel à une zone
 | ||||
| uint8_t sameColor(Pixel *t_pixel, Zone *t_zone); | ||||
| int32_t sameColor(Pixel *t_pixel, Zone *t_zone); | ||||
| /// Ajoute un pixel et ses pixels connexes à une zone
 | ||||
| void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone); | ||||
| /// Sélectionne la zone correspondant à la couleur d'un pixel
 | ||||
| void chooseZoneForPixel(Image *t_img, int64_t t_idx, darray *zones); | ||||
| /// Créé les zones d'une image
 | ||||
| darray *imgToZones(Image *t_img); | ||||
| /// Écrit tous les \ref Segment d’une zone dans le fichier de sortie
 | ||||
| void write_segments(FILE *t_output, darray *t_segments); | ||||
| /// Écrit les données compressées dans le fichier de sortie
 | ||||
| void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones); | ||||
| /// Compresse l'image d'entrée
 | ||||
| void compress(const char *t_input_file, const char *t_output_file); | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/darray.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/darray.c
									
									
									
									
									
								
							| @ -17,7 +17,7 @@ | ||||
|  * \param[in] t_element_size Taille des objets stockés | ||||
|  * \return Pointeur sur le nouvel objet \ref darray | ||||
|  */ | ||||
| darray *darrayNew(size_t t_element_size) { | ||||
| darray *darrayNew(uint64_t t_element_size) { | ||||
|   darray *ret; | ||||
|   ret = (darray *)malloc(sizeof(darray)); | ||||
|   ret->begin = NULL; | ||||
| @ -61,7 +61,7 @@ void darrayInsert(darray *t_self, void *t_pos, void *t_elem) { | ||||
|  */ | ||||
| void darrayExtend(darray *t_self) { | ||||
|   void *new_array; | ||||
|   size_t size; | ||||
|   uint64_t size; | ||||
|   size = darraySize(t_self); | ||||
|   new_array = | ||||
|       realloc(t_self->begin, (darraySize(t_self) + 1) * t_self->element_size); | ||||
| @ -136,8 +136,8 @@ void darrayDelete(darray *t_self) { | ||||
|  * d’éléments | ||||
|  * \return Nombre d’éléments contenus dans `self` | ||||
|  */ | ||||
| size_t darraySize(darray *t_self) { | ||||
|   return (size_t)((char *)t_self->end - (char *)t_self->begin) / | ||||
| uint64_t darraySize(darray *t_self) { | ||||
|   return (uint64_t)((char *)t_self->end - (char *)t_self->begin) / | ||||
|          t_self->element_size; | ||||
| } | ||||
| 
 | ||||
| @ -153,7 +153,7 @@ size_t darraySize(darray *t_self) { | ||||
|  * \return Pointeur de type `void*` pointant sur l’élément si l’index est | ||||
|  * valide, sur NULL sinon. | ||||
|  */ | ||||
| void *darrayGet(darray *t_self, size_t t_idx) { | ||||
| void *darrayGet(darray *t_self, uint64_t t_idx) { | ||||
|   if (t_idx >= darraySize(t_self)) { | ||||
|     fprintf(stderr, "Error in `darrayGet`, out of bound idx: %zu (max: %zu)\n", | ||||
|             t_idx, darraySize(t_self)); | ||||
|  | ||||
							
								
								
									
										13
									
								
								src/darray.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/darray.h
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ | ||||
| #define SRC_DARRAY_H_ | ||||
| 
 | ||||
| #include "errorcodes.h" | ||||
| #include <stdint.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| /**
 | ||||
| @ -21,12 +22,12 @@ typedef struct { | ||||
|   void *begin; /*!< Pointeur sur le premier élément du tableau */ | ||||
|   void *end; /*!< Pointeur sur l’élément situé immédiatement après le dernier
 | ||||
|                 élément du tableau */ | ||||
|   size_t element_size; /*!< Taille des éléments stockés dans le tableau */ | ||||
|   size_t capacity; /*!< Capacité maximale du tableau actuel */ | ||||
|   uint64_t element_size; /*!< Taille des éléments stockés dans le tableau */ | ||||
|   uint64_t capacity;     /*!< Capacité maximale du tableau actuel */ | ||||
| } darray; | ||||
| 
 | ||||
| /// \brief Créé un nouvel objet \ref darray vide
 | ||||
| darray *darrayNew(size_t element_size); | ||||
| darray *darrayNew(uint64_t element_size); | ||||
| /// \brief Augmente la capacité d'un \ref darray
 | ||||
| void darrayExtend(darray *self); | ||||
| /// \brief Insère un élément à l’endroit pointé dans un \ref darray
 | ||||
| @ -34,7 +35,7 @@ void darrayInsert(darray *self, void *pos, void *elem); | ||||
| /// \brief Supprime l’élément pointé dans l’objet \ref darray
 | ||||
| void darrayErase(darray *self, void *pos); | ||||
| /// \brief Retourne l’élément du \ref darray au idx-ème index
 | ||||
| void *darrayGet(darray *self, size_t idx); | ||||
| void *darrayGet(darray *self, uint64_t idx); | ||||
| /// \brief Insère un élément à la fin de l’élément \ref darray
 | ||||
| void darrayPushBack(darray *self, void *elem); | ||||
| /// \brief Supprime le dernier élément de l’élément \ref darray
 | ||||
| @ -42,8 +43,8 @@ void darrayPopBack(darray *self); | ||||
| /// \brief Détruit l’élément \ref darray
 | ||||
| void darrayDelete(darray *self); | ||||
| /// \brief Renvoie la taille de l’élément \ref darray
 | ||||
| size_t darraySize(darray *self); | ||||
| uint64_t darraySize(darray *self); | ||||
| /// \brief Renvoie la taille de l’élément \ref darray
 | ||||
| size_t darrayElemSize(darray *self); | ||||
| uint64_t darrayElemSize(darray *self); | ||||
| 
 | ||||
| #endif /* SRC_DARRAY_H_ */ | ||||
|  | ||||
| @ -9,6 +9,7 @@ | ||||
|  */ | ||||
| 
 | ||||
| #include "compress.h" | ||||
| #include "uncompress.h" | ||||
| #include <getopt.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| @ -93,7 +94,7 @@ Argres process_args(const int t_argc, char *t_argv[]) { | ||||
|   Argres res; | ||||
|   res.input = NULL; | ||||
|   res.compress = 1; | ||||
|   res.output = "output.su"; | ||||
|   res.output = NULL; | ||||
|   while (1) { | ||||
|     int option_index = 0; | ||||
|     static struct option long_options[] = { | ||||
| @ -128,13 +129,10 @@ int main(int argc, char **argv) { | ||||
|     fprintf(stderr, "ERROR: no input file."); | ||||
|     help(ARGERROR); | ||||
|   } | ||||
|   DEBUG { | ||||
|     printf("input: %s\noutput: %s\n", argresults.input, argresults.output); | ||||
|   } | ||||
|   if(argresults.compress) { | ||||
|     compress(argresults.input, argresults.output); | ||||
|   } else { | ||||
|     puts("Uncompressing..."); | ||||
|     uncompress(argresults.input, argresults.output); | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
							
								
								
									
										25
									
								
								src/ppm.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								src/ppm.c
									
									
									
									
									
								
							| @ -77,7 +77,7 @@ void check_for_comments(FILE *t_fp) { | ||||
|  *  \param[in] t_filename Nom du fichier ouvert | ||||
|  */ | ||||
| void read_file_size(FILE *t_fp, Image *t_img, const char *t_filename) { | ||||
|   if (fscanf(t_fp, "%lu %lu", &t_img->x, &t_img->y) != 2) { | ||||
|   if (fscanf(t_fp, "%lu %lu", &t_img->sizeX, &t_img->sizeY) != 2) { | ||||
|     fprintf(stderr, "Invalid image size (error loading '%s')\n", t_filename); | ||||
|     exit(FILE_FORMAT_ERROR); | ||||
|   } | ||||
| @ -143,7 +143,6 @@ void read_data(FILE *t_fp, uint64_t t_size, unsigned char **t_data, | ||||
| void dataToImage(Image *t_img, uint8_t *t_data, uint64_t t_size) { | ||||
|   uint64_t i; | ||||
|   t_img->pixels = darrayNew(sizeof(Pixel)); | ||||
|   printf("Size of data: %lu\n", t_size); | ||||
|   for (i = 0; i < t_size; i += 3) { | ||||
|     darrayPushBack(t_img->pixels, | ||||
|                    newPixel(t_data[i], t_data[i + 1], t_data[i + 2])); | ||||
| @ -166,9 +165,9 @@ uint8_t *imageToData(Image *t_img) { | ||||
|   data = (uint8_t *)malloc(3 * sizeof(uint8_t) * size); | ||||
|   for (i = 0; i < size; i += 3) { | ||||
|     pixel = darrayGet(t_img->pixels, i / 3); | ||||
|     data[i] = pixel->r; | ||||
|     data[i + 1] = pixel->g; | ||||
|     data[i + 2] = pixel->b; | ||||
|     data[i] = pixel->red; | ||||
|     data[i + 1] = pixel->green; | ||||
|     data[i + 2] = pixel->blue; | ||||
|   } | ||||
|   return data; | ||||
| } | ||||
| @ -192,11 +191,7 @@ int imageLoadPPM(const char *t_filename, Image *t_img) { | ||||
|   check_for_comments(fp);                /* check for comments */ | ||||
|   read_file_size(fp, t_img, t_filename); /* read image size information */ | ||||
|   read_rgb(fp, t_filename);              /* read rgb component */ | ||||
|   DEBUG { | ||||
|     printf("Size image %lu %lu => %lu\n", t_img->x, t_img->y, | ||||
|            t_img->x * t_img->y); | ||||
|   } | ||||
|   size = t_img->x * t_img->y * 3; | ||||
|   size = t_img->sizeX * t_img->sizeY * 3; | ||||
|   read_data(fp, size, &data, t_filename); /* read data from file */ | ||||
|   dataToImage(t_img, data, size); | ||||
|   free(data); | ||||
| @ -211,17 +206,15 @@ int imageLoadPPM(const char *t_filename, Image *t_img) { | ||||
|  *  \param[in] t_filename Nom du fichier image à ouvrir | ||||
|  *  \param[in] t_img Objet \ref Image à écrire | ||||
|  */ | ||||
| void imageSavePPM(char *t_filename, Image *t_img) { | ||||
| void imageSavePPM(const char *t_filename, Image *t_img, uint8_t *t_data) { | ||||
|   FILE *fp; | ||||
|   uint8_t *data; | ||||
|   fp = get_file(t_filename, "wb"); /* open file for output */ | ||||
|   /* write the header file */ | ||||
|   fprintf(fp, "P6\n");                                  /* image format */ | ||||
|   fprintf(fp, "# Created by %s\n", CREATOR);            /* comments */ | ||||
|   fprintf(fp, "%lu %lu\n", t_img->y, t_img->y); /* image size */ | ||||
|   fprintf(fp, "%lu %lu\n", t_img->sizeY, t_img->sizeY); /* image size */ | ||||
|   fprintf(fp, "%d\n", RGB_COMPONENT_COLOR); /* rgb component depth */ | ||||
|   data = imageToData(t_img);                    /* pixel data */ | ||||
|   fwrite(data, (size_t)1, (size_t)(3 * t_img->x * t_img->y), fp); | ||||
|   free(data); | ||||
|   fwrite(t_data, (size_t)1, (size_t)(3 * t_img->sizeX * t_img->sizeY), fp); | ||||
|   free(t_data); | ||||
|   fclose(fp); | ||||
| } | ||||
|  | ||||
| @ -32,6 +32,6 @@ unsigned char *imageToData(Image *t_img); | ||||
| /// \brief Ouverture et lecture de l’image d’entrée
 | ||||
| int imageLoadPPM(const char *t_filename, Image *t_img); | ||||
| /// \brief Ouverture et écriture de l'image de sortie
 | ||||
| void imageSavePPM(char *t_filename, Image *t_img); | ||||
| void imageSavePPM(const char *t_filename, Image *t_img, uint8_t *data); | ||||
| 
 | ||||
| #endif /* SRC_PPM_H_ */ | ||||
|  | ||||
							
								
								
									
										127
									
								
								src/uncompress.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/uncompress.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | ||||
| /**
 | ||||
|  *   \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); | ||||
| } | ||||
							
								
								
									
										27
									
								
								src/uncompress.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/uncompress.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| /**
 | ||||
|  *   \file uncompress.h | ||||
|  *   \brief Décompression de fichiers | ||||
|  * | ||||
|  *  Ce fichier contient les déclarations des fonctions nécessaires à | ||||
|  *  décompresser un fichier en `.su` généré par ce programme vers un fichier | ||||
|  *  `.ppm` identique à l’original. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #ifndef SRC_UNCOMPRESS_H_ | ||||
| #define SRC_UNCOMPRESS_H_ | ||||
| 
 | ||||
| #include "ppm.h" | ||||
| 
 | ||||
| #define DEFAULT_UNCOMPRESSED_FILE "output.ppm" | ||||
| 
 | ||||
| /// Lit les segments compressés dans une zone
 | ||||
| void read_compressed_zones(FILE *t_file, darray *t_zones); | ||||
| /// Lit les zones compressées dans le fichier d’entrée
 | ||||
| void read_compressed_file_data(FILE *t_file, darray *zones); | ||||
| /// Lit les premières données du fichier compressé
 | ||||
| void read_compressed_file_meta(FILE *t_file, Image *t_img); | ||||
| /// Décompresse le fichier d’entrée dans le fichier de sortie
 | ||||
| void uncompress(const char *t_input_file, const char *t_output_file); | ||||
| 
 | ||||
| #endif /* SRC_UNCOMPRESS_H_ */ | ||||
| @ -21,9 +21,9 @@ | ||||
| Pixel *newPixel(uint8_t t_r, uint8_t t_g, uint8_t t_b) { | ||||
|   Pixel *res; | ||||
|   res = (Pixel *)malloc(sizeof(Pixel)); | ||||
|   res->r = t_r; | ||||
|   res->g = t_g; | ||||
|   res->b = t_b; | ||||
|   res->red = t_r; | ||||
|   res->green = t_g; | ||||
|   res->blue = t_b; | ||||
|   res->visited = 0; | ||||
|   return res; | ||||
| } | ||||
| @ -38,8 +38,8 @@ Pixel *newPixel(uint8_t t_r, uint8_t t_g, uint8_t t_b) { | ||||
| Image *newImage() { | ||||
|   Image *res; | ||||
|   res = (Image *)malloc(sizeof(Image)); | ||||
|   res->x = 0; | ||||
|   res->y = 0; | ||||
|   res->sizeX = 0; | ||||
|   res->sizeY = 0; | ||||
|   res->pixels = darrayNew(sizeof(Pixel)); | ||||
|   return res; | ||||
| } | ||||
| @ -53,7 +53,6 @@ Image *newImage() { | ||||
|  *  \param[in] t_self Conteneur d’image à détruire | ||||
|  */ | ||||
| void deleteImage(Image *t_self) { | ||||
|   DEBUG { printf("deleted all pixels\n"); } | ||||
|   darrayDelete(t_self->pixels); | ||||
|   free(t_self); | ||||
| } | ||||
| @ -88,17 +87,9 @@ Segment *newSegment(uint32_t t_right_limit, uint32_t t_left_limit) { | ||||
|  */ | ||||
| Zone *newZone(uint8_t t_r, uint8_t t_g, uint8_t t_b) { | ||||
|   Zone *res = (Zone *)malloc(sizeof(Zone)); | ||||
|   res->r = t_r; | ||||
|   res->g = t_g; | ||||
|   res->b = t_b; | ||||
|   res->red = t_r; | ||||
|   res->green = t_g; | ||||
|   res->blue = t_b; | ||||
|   res->segments = darrayNew(sizeof(Segment)); | ||||
|   return res; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  *  Destructeur de zone, libère la zone mémoire utilisée pour stocker les | ||||
|  *  segments. Ne libère pas \p t_self lui-même mais son membre `segments`. | ||||
|  * | ||||
|  *  \param[in] t_self Conteneur de zone à détruire | ||||
|  */ | ||||
| void deleteZoneContent(Zone *t_self) { darrayDelete(t_self->segments); } | ||||
|  | ||||
| @ -11,7 +11,6 @@ | ||||
| #define SRC_UTILITIES_H_ | ||||
| 
 | ||||
| #include "darray.h" | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| /*****************************************************************************/ | ||||
| @ -50,9 +49,9 @@ typedef struct Segment Segment; | ||||
|  *  dans un tableau dynamique \ref darray. | ||||
|  */ | ||||
| struct Image { | ||||
|   uint64_t x;     /*!< Largeur de l’image */ | ||||
|   uint64_t y;     /*!< Hauteur de l’image */ | ||||
|   darray *pixels; /*!< Vecteur à une dimention de pixels */ | ||||
|   uint64_t sizeX; /*!< Largeur de l’image */ | ||||
|   uint64_t sizeY; /*!< Hauteur de l’image */ | ||||
|   darray *pixels; /*!< Vecteur à une dimention de \ref Pixel */ | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -63,9 +62,9 @@ struct Image { | ||||
|  *  visité précédemment par l’algorithme de compression. | ||||
|  */ | ||||
| struct Pixel { | ||||
|   uint8_t r;             /*!< Couleur rouge du pixel */ | ||||
|   uint8_t g;             /*!< Couleur verte du pixel */ | ||||
|   uint8_t b;             /*!< Couleur bleue du pixel */ | ||||
|   uint8_t red;     /*!< Couleur rouge du pixel */ | ||||
|   uint8_t green;   /*!< Couleur verte du pixel */ | ||||
|   uint8_t blue;    /*!< Couleur bleue du pixel */ | ||||
|   uint8_t visited; /*!< Le pixel a-t-il été visité avant */ | ||||
| }; | ||||
| 
 | ||||
| @ -76,10 +75,10 @@ struct Pixel { | ||||
|  *  dont on conserve uniquement les marges dans le tableau dynamique. | ||||
|  */ | ||||
| struct Zone { | ||||
|   uint8_t r;        /*!< Couleur rouge de la zone */ | ||||
|   uint8_t g;        /*!< Couleur verte de la zone */ | ||||
|   uint8_t b;        /*!< Couleur bleue de la zone */ | ||||
|   darray *segments; /*!< Vecteur de segments */ | ||||
|   uint8_t red;      /*!< Couleur rouge de la zone */ | ||||
|   uint8_t green;    /*!< Couleur verte de la zone */ | ||||
|   uint8_t blue;     /*!< Couleur bleue de la zone */ | ||||
|   darray *segments; /*!< Vecteur de \ref Segment */ | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
| @ -108,7 +107,5 @@ void deleteImage(Image *t_self); | ||||
| Segment *newSegment(uint32_t t_right_limit, uint32_t t_left_limit); | ||||
| /// \brief Constructeur de conteneur de zone
 | ||||
| Zone *newZone(uint8_t t_r, uint8_t t_g, uint8_t t_b); | ||||
| /// \brief Destructeur de conteneur de zone
 | ||||
| void deleteZoneContent(Zone *t_self); | ||||
| 
 | ||||
| #endif /* SRC_UTILITIES_H_ */ | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user