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/html
|
||||||
@rm -rf doc/latex
|
@rm -rf doc/latex
|
||||||
@rm -rf gmon.out
|
@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
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# 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
|
# 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
|
# 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
|
* \param[in] t_zone Zone à laquelle le pixel est éligible ou non
|
||||||
* \return Valeur booléenne, `1` si le pixel est éligible, `0` sinon
|
* \return Valeur booléenne, `1` si le pixel est éligible, `0` sinon
|
||||||
*/
|
*/
|
||||||
uint8_t sameColor(Pixel *t_pixel, Zone *t_zone) {
|
int32_t sameColor(Pixel *t_pixel, Zone *t_zone) {
|
||||||
return (t_pixel->r == t_zone->r && t_pixel->g == t_zone->g &&
|
return (t_pixel->red == t_zone->red && t_pixel->green == t_zone->green &&
|
||||||
t_pixel->b == t_zone->b)
|
t_pixel->blue == t_zone->blue)
|
||||||
? 1
|
? 1
|
||||||
: 0;
|
: 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) {
|
void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone) {
|
||||||
const size_t img_size = darraySize(t_img->pixels);
|
const size_t img_size = darraySize(t_img->pixels);
|
||||||
Pixel *current_pixel;
|
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;
|
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) {
|
if (t_idx >= (int64_t)img_size || t_idx < 0) {
|
||||||
return;
|
return;
|
||||||
@ -56,7 +56,7 @@ void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone) {
|
|||||||
current_pixel->visited = 1;
|
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 */
|
--left_limit) { /* fetch right limit of segment */
|
||||||
current_pixel = darrayGet(t_img->pixels, (size_t)left_limit);
|
current_pixel = darrayGet(t_img->pixels, (size_t)left_limit);
|
||||||
if (current_pixel->visited || !sameColor(current_pixel, t_zone)) {
|
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));
|
newSegment((uint32_t)right_limit, (uint32_t)left_limit));
|
||||||
for (; left_limit <= right_limit;
|
for (; left_limit <= right_limit;
|
||||||
++left_limit) { /* process every pixel up and down the segment */
|
++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
|
/* 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
|
* 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);
|
darrayPushBack(t_zones, current_zone);
|
||||||
addPixelToSelectedZone(t_img, t_idx, current_zone);
|
addPixelToSelectedZone(t_img, t_idx, current_zone);
|
||||||
}
|
}
|
||||||
@ -127,20 +127,52 @@ darray *imgToZones(Image *t_img) {
|
|||||||
return zones;
|
return zones;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_compressed_file(Image *t_img, FILE *t_output, darray *t_zones) {
|
/**
|
||||||
size_t i, j;
|
* Cette fonction écrit dans \p t_output la taille en `uint64_t` de la zone,
|
||||||
Zone *current_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;
|
Segment *segment;
|
||||||
fwrite(&t_img->x, sizeof(t_img->x), 2, t_output);
|
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) {
|
for (i = 0; i < darraySize(t_zones); ++i) {
|
||||||
current_zone = darrayGet(t_zones, i);
|
current_zone = darrayGet(t_zones, i);
|
||||||
fwrite(¤t_zone->r, sizeof(current_zone->r) * 3, 1, t_output);
|
fwrite(¤t_zone->red, sizeof(current_zone->red) * 3, 1, t_output);
|
||||||
for (j = 0; j < darraySize(current_zone->segments); ++j) {
|
write_segments(t_output, current_zone->segments);
|
||||||
segment = darrayGet(current_zone->segments, j);
|
|
||||||
fwrite(&segment->right_limit, sizeof(Segment), 1, t_output);
|
|
||||||
}
|
|
||||||
darrayDelete(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;
|
Image *img;
|
||||||
darray *zones;
|
darray *zones;
|
||||||
FILE *output_file;
|
FILE *output_file;
|
||||||
|
if (!t_output_file) {
|
||||||
|
t_output_file = DEFAULT_COMPRESSED_NAME;
|
||||||
|
}
|
||||||
img = newImage();
|
img = newImage();
|
||||||
imageLoadPPM(t_input_file, img);
|
imageLoadPPM(t_input_file, img);
|
||||||
output_file = get_file(t_output_file, "wb");
|
output_file = get_file(t_output_file, "wb");
|
||||||
zones = imgToZones(img);
|
zones = imgToZones(img);
|
||||||
write_compressed_file(img, output_file, zones);
|
write_compressed_file(img, output_file, zones);
|
||||||
deleteImage(img);
|
deleteImage(img);
|
||||||
darrayDelete(zones);
|
|
||||||
fclose(output_file);
|
fclose(output_file);
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,20 @@
|
|||||||
|
|
||||||
#include "ppm.h"
|
#include "ppm.h"
|
||||||
|
|
||||||
|
#define DEFAULT_COMPRESSED_NAME "output.su"
|
||||||
|
|
||||||
/// Teste l’éligibilité d’un pixel à une zone
|
/// 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
|
/// Ajoute un pixel et ses pixels connexes à une zone
|
||||||
void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone);
|
void addPixelToSelectedZone(Image *t_img, int64_t t_idx, Zone *t_zone);
|
||||||
/// Sélectionne la zone correspondant à la couleur d'un pixel
|
/// Sélectionne la zone correspondant à la couleur d'un pixel
|
||||||
void chooseZoneForPixel(Image *t_img, int64_t t_idx, darray *zones);
|
void chooseZoneForPixel(Image *t_img, int64_t t_idx, darray *zones);
|
||||||
/// Créé les zones d'une image
|
/// Créé les zones d'une image
|
||||||
darray *imgToZones(Image *t_img);
|
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
|
/// Compresse l'image d'entrée
|
||||||
void compress(const char *t_input_file, const char *t_output_file);
|
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
|
* \param[in] t_element_size Taille des objets stockés
|
||||||
* \return Pointeur sur le nouvel objet \ref darray
|
* \return Pointeur sur le nouvel objet \ref darray
|
||||||
*/
|
*/
|
||||||
darray *darrayNew(size_t t_element_size) {
|
darray *darrayNew(uint64_t t_element_size) {
|
||||||
darray *ret;
|
darray *ret;
|
||||||
ret = (darray *)malloc(sizeof(darray));
|
ret = (darray *)malloc(sizeof(darray));
|
||||||
ret->begin = NULL;
|
ret->begin = NULL;
|
||||||
@ -61,7 +61,7 @@ void darrayInsert(darray *t_self, void *t_pos, void *t_elem) {
|
|||||||
*/
|
*/
|
||||||
void darrayExtend(darray *t_self) {
|
void darrayExtend(darray *t_self) {
|
||||||
void *new_array;
|
void *new_array;
|
||||||
size_t size;
|
uint64_t size;
|
||||||
size = darraySize(t_self);
|
size = darraySize(t_self);
|
||||||
new_array =
|
new_array =
|
||||||
realloc(t_self->begin, (darraySize(t_self) + 1) * t_self->element_size);
|
realloc(t_self->begin, (darraySize(t_self) + 1) * t_self->element_size);
|
||||||
@ -136,8 +136,8 @@ void darrayDelete(darray *t_self) {
|
|||||||
* d’éléments
|
* d’éléments
|
||||||
* \return Nombre d’éléments contenus dans `self`
|
* \return Nombre d’éléments contenus dans `self`
|
||||||
*/
|
*/
|
||||||
size_t darraySize(darray *t_self) {
|
uint64_t darraySize(darray *t_self) {
|
||||||
return (size_t)((char *)t_self->end - (char *)t_self->begin) /
|
return (uint64_t)((char *)t_self->end - (char *)t_self->begin) /
|
||||||
t_self->element_size;
|
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
|
* \return Pointeur de type `void*` pointant sur l’élément si l’index est
|
||||||
* valide, sur NULL sinon.
|
* 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)) {
|
if (t_idx >= darraySize(t_self)) {
|
||||||
fprintf(stderr, "Error in `darrayGet`, out of bound idx: %zu (max: %zu)\n",
|
fprintf(stderr, "Error in `darrayGet`, out of bound idx: %zu (max: %zu)\n",
|
||||||
t_idx, darraySize(t_self));
|
t_idx, darraySize(t_self));
|
||||||
|
13
src/darray.h
13
src/darray.h
@ -8,6 +8,7 @@
|
|||||||
#define SRC_DARRAY_H_
|
#define SRC_DARRAY_H_
|
||||||
|
|
||||||
#include "errorcodes.h"
|
#include "errorcodes.h"
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,12 +22,12 @@ typedef struct {
|
|||||||
void *begin; /*!< Pointeur sur le premier élément du tableau */
|
void *begin; /*!< Pointeur sur le premier élément du tableau */
|
||||||
void *end; /*!< Pointeur sur l’élément situé immédiatement après le dernier
|
void *end; /*!< Pointeur sur l’élément situé immédiatement après le dernier
|
||||||
élément du tableau */
|
élément du tableau */
|
||||||
size_t element_size; /*!< Taille des éléments stockés dans le tableau */
|
uint64_t element_size; /*!< Taille des éléments stockés dans le tableau */
|
||||||
size_t capacity; /*!< Capacité maximale du tableau actuel */
|
uint64_t capacity; /*!< Capacité maximale du tableau actuel */
|
||||||
} darray;
|
} darray;
|
||||||
|
|
||||||
/// \brief Créé un nouvel objet \ref darray vide
|
/// \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
|
/// \brief Augmente la capacité d'un \ref darray
|
||||||
void darrayExtend(darray *self);
|
void darrayExtend(darray *self);
|
||||||
/// \brief Insère un élément à l’endroit pointé dans un \ref darray
|
/// \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
|
/// \brief Supprime l’élément pointé dans l’objet \ref darray
|
||||||
void darrayErase(darray *self, void *pos);
|
void darrayErase(darray *self, void *pos);
|
||||||
/// \brief Retourne l’élément du \ref darray au idx-ème index
|
/// \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
|
/// \brief Insère un élément à la fin de l’élément \ref darray
|
||||||
void darrayPushBack(darray *self, void *elem);
|
void darrayPushBack(darray *self, void *elem);
|
||||||
/// \brief Supprime le dernier élément de l’élément \ref darray
|
/// \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
|
/// \brief Détruit l’élément \ref darray
|
||||||
void darrayDelete(darray *self);
|
void darrayDelete(darray *self);
|
||||||
/// \brief Renvoie la taille de l’élément \ref darray
|
/// \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
|
/// \brief Renvoie la taille de l’élément \ref darray
|
||||||
size_t darrayElemSize(darray *self);
|
uint64_t darrayElemSize(darray *self);
|
||||||
|
|
||||||
#endif /* SRC_DARRAY_H_ */
|
#endif /* SRC_DARRAY_H_ */
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "compress.h"
|
#include "compress.h"
|
||||||
|
#include "uncompress.h"
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ Argres process_args(const int t_argc, char *t_argv[]) {
|
|||||||
Argres res;
|
Argres res;
|
||||||
res.input = NULL;
|
res.input = NULL;
|
||||||
res.compress = 1;
|
res.compress = 1;
|
||||||
res.output = "output.su";
|
res.output = NULL;
|
||||||
while (1) {
|
while (1) {
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
@ -128,13 +129,10 @@ int main(int argc, char **argv) {
|
|||||||
fprintf(stderr, "ERROR: no input file.");
|
fprintf(stderr, "ERROR: no input file.");
|
||||||
help(ARGERROR);
|
help(ARGERROR);
|
||||||
}
|
}
|
||||||
DEBUG {
|
|
||||||
printf("input: %s\noutput: %s\n", argresults.input, argresults.output);
|
|
||||||
}
|
|
||||||
if(argresults.compress) {
|
if(argresults.compress) {
|
||||||
compress(argresults.input, argresults.output);
|
compress(argresults.input, argresults.output);
|
||||||
} else {
|
} else {
|
||||||
puts("Uncompressing...");
|
uncompress(argresults.input, argresults.output);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
31
src/ppm.c
31
src/ppm.c
@ -77,7 +77,7 @@ void check_for_comments(FILE *t_fp) {
|
|||||||
* \param[in] t_filename Nom du fichier ouvert
|
* \param[in] t_filename Nom du fichier ouvert
|
||||||
*/
|
*/
|
||||||
void read_file_size(FILE *t_fp, Image *t_img, const char *t_filename) {
|
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);
|
fprintf(stderr, "Invalid image size (error loading '%s')\n", t_filename);
|
||||||
exit(FILE_FORMAT_ERROR);
|
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) {
|
void dataToImage(Image *t_img, uint8_t *t_data, uint64_t t_size) {
|
||||||
uint64_t i;
|
uint64_t i;
|
||||||
t_img->pixels = darrayNew(sizeof(Pixel));
|
t_img->pixels = darrayNew(sizeof(Pixel));
|
||||||
printf("Size of data: %lu\n", t_size);
|
|
||||||
for (i = 0; i < t_size; i += 3) {
|
for (i = 0; i < t_size; i += 3) {
|
||||||
darrayPushBack(t_img->pixels,
|
darrayPushBack(t_img->pixels,
|
||||||
newPixel(t_data[i], t_data[i + 1], t_data[i + 2]));
|
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);
|
data = (uint8_t *)malloc(3 * sizeof(uint8_t) * size);
|
||||||
for (i = 0; i < size; i += 3) {
|
for (i = 0; i < size; i += 3) {
|
||||||
pixel = darrayGet(t_img->pixels, i / 3);
|
pixel = darrayGet(t_img->pixels, i / 3);
|
||||||
data[i] = pixel->r;
|
data[i] = pixel->red;
|
||||||
data[i + 1] = pixel->g;
|
data[i + 1] = pixel->green;
|
||||||
data[i + 2] = pixel->b;
|
data[i + 2] = pixel->blue;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@ -192,11 +191,7 @@ int imageLoadPPM(const char *t_filename, Image *t_img) {
|
|||||||
check_for_comments(fp); /* check for comments */
|
check_for_comments(fp); /* check for comments */
|
||||||
read_file_size(fp, t_img, t_filename); /* read image size information */
|
read_file_size(fp, t_img, t_filename); /* read image size information */
|
||||||
read_rgb(fp, t_filename); /* read rgb component */
|
read_rgb(fp, t_filename); /* read rgb component */
|
||||||
DEBUG {
|
size = t_img->sizeX * t_img->sizeY * 3;
|
||||||
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;
|
|
||||||
read_data(fp, size, &data, t_filename); /* read data from file */
|
read_data(fp, size, &data, t_filename); /* read data from file */
|
||||||
dataToImage(t_img, data, size);
|
dataToImage(t_img, data, size);
|
||||||
free(data);
|
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_filename Nom du fichier image à ouvrir
|
||||||
* \param[in] t_img Objet \ref Image à écrire
|
* \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;
|
FILE *fp;
|
||||||
uint8_t *data;
|
|
||||||
fp = get_file(t_filename, "wb"); /* open file for output */
|
fp = get_file(t_filename, "wb"); /* open file for output */
|
||||||
/* write the header file */
|
/* write the header file */
|
||||||
fprintf(fp, "P6\n"); /* image format */
|
fprintf(fp, "P6\n"); /* image format */
|
||||||
fprintf(fp, "# Created by %s\n", CREATOR); /* comments */
|
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 */
|
fprintf(fp, "%d\n", RGB_COMPONENT_COLOR); /* rgb component depth */
|
||||||
data = imageToData(t_img); /* pixel data */
|
fwrite(t_data, (size_t)1, (size_t)(3 * t_img->sizeX * t_img->sizeY), fp);
|
||||||
fwrite(data, (size_t)1, (size_t)(3 * t_img->x * t_img->y), fp);
|
free(t_data);
|
||||||
free(data);
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,6 @@ unsigned char *imageToData(Image *t_img);
|
|||||||
/// \brief Ouverture et lecture de l’image d’entrée
|
/// \brief Ouverture et lecture de l’image d’entrée
|
||||||
int imageLoadPPM(const char *t_filename, Image *t_img);
|
int imageLoadPPM(const char *t_filename, Image *t_img);
|
||||||
/// \brief Ouverture et écriture de l'image de sortie
|
/// \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_ */
|
#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 *newPixel(uint8_t t_r, uint8_t t_g, uint8_t t_b) {
|
||||||
Pixel *res;
|
Pixel *res;
|
||||||
res = (Pixel *)malloc(sizeof(Pixel));
|
res = (Pixel *)malloc(sizeof(Pixel));
|
||||||
res->r = t_r;
|
res->red = t_r;
|
||||||
res->g = t_g;
|
res->green = t_g;
|
||||||
res->b = t_b;
|
res->blue = t_b;
|
||||||
res->visited = 0;
|
res->visited = 0;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -38,8 +38,8 @@ Pixel *newPixel(uint8_t t_r, uint8_t t_g, uint8_t t_b) {
|
|||||||
Image *newImage() {
|
Image *newImage() {
|
||||||
Image *res;
|
Image *res;
|
||||||
res = (Image *)malloc(sizeof(Image));
|
res = (Image *)malloc(sizeof(Image));
|
||||||
res->x = 0;
|
res->sizeX = 0;
|
||||||
res->y = 0;
|
res->sizeY = 0;
|
||||||
res->pixels = darrayNew(sizeof(Pixel));
|
res->pixels = darrayNew(sizeof(Pixel));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -53,7 +53,6 @@ Image *newImage() {
|
|||||||
* \param[in] t_self Conteneur d’image à détruire
|
* \param[in] t_self Conteneur d’image à détruire
|
||||||
*/
|
*/
|
||||||
void deleteImage(Image *t_self) {
|
void deleteImage(Image *t_self) {
|
||||||
DEBUG { printf("deleted all pixels\n"); }
|
|
||||||
darrayDelete(t_self->pixels);
|
darrayDelete(t_self->pixels);
|
||||||
free(t_self);
|
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 *newZone(uint8_t t_r, uint8_t t_g, uint8_t t_b) {
|
||||||
Zone *res = (Zone *)malloc(sizeof(Zone));
|
Zone *res = (Zone *)malloc(sizeof(Zone));
|
||||||
res->r = t_r;
|
res->red = t_r;
|
||||||
res->g = t_g;
|
res->green = t_g;
|
||||||
res->b = t_b;
|
res->blue = t_b;
|
||||||
res->segments = darrayNew(sizeof(Segment));
|
res->segments = darrayNew(sizeof(Segment));
|
||||||
return res;
|
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_
|
#define SRC_UTILITIES_H_
|
||||||
|
|
||||||
#include "darray.h"
|
#include "darray.h"
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -50,9 +49,9 @@ typedef struct Segment Segment;
|
|||||||
* dans un tableau dynamique \ref darray.
|
* dans un tableau dynamique \ref darray.
|
||||||
*/
|
*/
|
||||||
struct Image {
|
struct Image {
|
||||||
uint64_t x; /*!< Largeur de l’image */
|
uint64_t sizeX; /*!< Largeur de l’image */
|
||||||
uint64_t y; /*!< Hauteur de l’image */
|
uint64_t sizeY; /*!< Hauteur de l’image */
|
||||||
darray *pixels; /*!< Vecteur à une dimention de pixels */
|
darray *pixels; /*!< Vecteur à une dimention de \ref Pixel */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,9 +62,9 @@ struct Image {
|
|||||||
* visité précédemment par l’algorithme de compression.
|
* visité précédemment par l’algorithme de compression.
|
||||||
*/
|
*/
|
||||||
struct Pixel {
|
struct Pixel {
|
||||||
uint8_t r; /*!< Couleur rouge du pixel */
|
uint8_t red; /*!< Couleur rouge du pixel */
|
||||||
uint8_t g; /*!< Couleur verte du pixel */
|
uint8_t green; /*!< Couleur verte du pixel */
|
||||||
uint8_t b; /*!< Couleur bleue du pixel */
|
uint8_t blue; /*!< Couleur bleue du pixel */
|
||||||
uint8_t visited; /*!< Le pixel a-t-il été visité avant */
|
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.
|
* dont on conserve uniquement les marges dans le tableau dynamique.
|
||||||
*/
|
*/
|
||||||
struct Zone {
|
struct Zone {
|
||||||
uint8_t r; /*!< Couleur rouge de la zone */
|
uint8_t red; /*!< Couleur rouge de la zone */
|
||||||
uint8_t g; /*!< Couleur verte de la zone */
|
uint8_t green; /*!< Couleur verte de la zone */
|
||||||
uint8_t b; /*!< Couleur bleue de la zone */
|
uint8_t blue; /*!< Couleur bleue de la zone */
|
||||||
darray *segments; /*!< Vecteur de segments */
|
darray *segments; /*!< Vecteur de \ref Segment */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +90,7 @@ struct Zone {
|
|||||||
*/
|
*/
|
||||||
struct Segment {
|
struct Segment {
|
||||||
uint32_t right_limit; /*!< extrême droit du segment */
|
uint32_t right_limit; /*!< extrême droit du segment */
|
||||||
uint32_t left_limit; /*!< extrême gauche du segment */
|
uint32_t left_limit; /*!< extrême gauche du segment */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -108,7 +107,5 @@ void deleteImage(Image *t_self);
|
|||||||
Segment *newSegment(uint32_t t_right_limit, uint32_t t_left_limit);
|
Segment *newSegment(uint32_t t_right_limit, uint32_t t_left_limit);
|
||||||
/// \brief Constructeur de conteneur de zone
|
/// \brief Constructeur de conteneur de zone
|
||||||
Zone *newZone(uint8_t t_r, uint8_t t_g, uint8_t t_b);
|
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_ */
|
#endif /* SRC_UTILITIES_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user