lots of structures, function helpers and documentation
This commit is contained in:
parent
2fedd3fa5b
commit
150ce6982a
@ -7,7 +7,7 @@ set(TGT "surfaces-unies")
|
|||||||
set(${TGT}_VERSION_MAJOR 0)
|
set(${TGT}_VERSION_MAJOR 0)
|
||||||
set(${TGT}_VERSION_MINOR 1)
|
set(${TGT}_VERSION_MINOR 1)
|
||||||
|
|
||||||
set(CC_COVERAGE_COMPILE_FLAGS "-pedantic -Wall -Wextra -Wfloat-equal -Wwrite-strings -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion -Wshadow -Wredundant-decls -Wdouble-promotion -Winit-self -Wswitch-default -Wswitch-enum -Wundef -Winline")
|
set(CC_COVERAGE_COMPILE_FLAGS "-pedantic -Wall -Wextra -Wfloat-equal -Wwrite-strings -Wpointer-arith -Wcast-qual -Wcast-align -Wconversion -Wshadow -Wredundant-decls -Wdouble-promotion -Winit-self -Wswitch-default -Wswitch-enum -Wundef -Winline -Werror")
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CC_COVERAGE_COMPILE_FLAGS} -DDebug -g -pg")
|
set(CMAKE_C_FLAGS_DEBUG "${CC_COVERAGE_COMPILE_FLAGS} -DDebug -g -pg")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CC_COVERAGE_COMPILE_FLAGS} -O3")
|
set(CMAKE_C_FLAGS_RELEASE "${CC_COVERAGE_COMPILE_FLAGS} -O3")
|
||||||
|
|
||||||
|
5
doc/.gitignore
vendored
Normal file
5
doc/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Ignore everything in this directory
|
||||||
|
*
|
||||||
|
# Except this file
|
||||||
|
!.gitignore
|
||||||
|
!Doxyfile
|
2430
doc/Doxyfile
Normal file
2430
doc/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
140
src/darray.c
Normal file
140
src/darray.c
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
/**
|
||||||
|
* \file darray.c
|
||||||
|
* \brief Implémentation des fonctions pour le type \ref darray_t
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <darray.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/// Constante pour les erreurs liées à \ref darray_t
|
||||||
|
#define PTR_ERROR 2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayNew` permet de créer un nouvel objet de type \ref darray_t ne
|
||||||
|
* contenant aucun élément. Le seul paramètre, `element_size`, est utilisé afin
|
||||||
|
* de connaître l’espace mémoire à allouer à chacun des éléments dans le
|
||||||
|
* tableau. Cela implique qu’un objet \ref darray_t ne peut contenir que des
|
||||||
|
* éléments du même type.
|
||||||
|
* \param element_size Taille des objets stockés
|
||||||
|
* \return Pointeur sur le nouvel objet \ref darray_t
|
||||||
|
*/
|
||||||
|
darray_t *darrayNew(size_t element_size) {
|
||||||
|
darray_t *ret;
|
||||||
|
ret = (darray_t *)malloc(sizeof(darray_t));
|
||||||
|
ret->begin = NULL;
|
||||||
|
ret->end = ret->begin;
|
||||||
|
ret->element_size = element_size;
|
||||||
|
ret->capacity = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayInsert` insère l’élément `elem` avant l'élément pointé par `pos` dans
|
||||||
|
* l’objet \ref darray_t. Cela décalera tous les éléments stockés dans \a `self`
|
||||||
|
* pen d’un cran vers la fin du tableau et insérera à l’endroit pointé le nouvel
|
||||||
|
* élément. Cette fonction modifie les membres `begin` et `end` et
|
||||||
|
* potentiellement `capacity` de `self`.
|
||||||
|
* \param self Objet \ref darray_t dans lequel on souhaite insérer un nouvel élément
|
||||||
|
* \param pos Position à laquelle on souhaite insérer un nouvel élément
|
||||||
|
* \param elem Élément que l’on souhaite insérer
|
||||||
|
*/
|
||||||
|
void darrayInsert(darray_t *self, void *pos, void *elem) {
|
||||||
|
void *new_array;
|
||||||
|
char *itr;
|
||||||
|
unsigned long pos_aux;
|
||||||
|
size_t size;
|
||||||
|
pos_aux = (char *)pos - (char *)self->begin;
|
||||||
|
if (darraySize(self) >= self->capacity) {
|
||||||
|
size = darraySize(self);
|
||||||
|
new_array =
|
||||||
|
realloc(self->begin, (darraySize(self) + 1) * self->element_size);
|
||||||
|
if (!new_array) {
|
||||||
|
fprintf(stderr, "Failed memory reallocation at %s:%d\nAborting...",
|
||||||
|
__FILE__, __LINE__ - 2);
|
||||||
|
exit(PTR_ERROR);
|
||||||
|
}
|
||||||
|
self->begin = new_array;
|
||||||
|
++self->capacity;
|
||||||
|
self->end = (char *)self->begin + size * self->element_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
itr = (char *)self->begin + pos_aux;
|
||||||
|
memmove(itr + self->element_size, itr, (char *)self->end - itr);
|
||||||
|
memcpy(itr, elem, self->element_size);
|
||||||
|
self->end = (char *)self->end + self->element_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayErase` supprime l’élément de objet \ref darray_t `self` pointé par
|
||||||
|
* `pos`. Cela décalera tous les éléments suivants dans le tableau d’un cran
|
||||||
|
* vers le début du tableau de manière à ce qu’il n’y aie pas d’élément vide
|
||||||
|
* entre les membres `begin` et `end` de `self`. Par ailleurs, le membre `end`
|
||||||
|
* de `self` se retrouve modifié par la fonction.
|
||||||
|
* \param self Objet \ref `darray_t` dont on souhaite supprimer un élément
|
||||||
|
* \param pos Élément de `self` que l’on souhaite supprimer
|
||||||
|
*/
|
||||||
|
void darrayErase(darray_t *self, void *pos) {
|
||||||
|
memmove(pos, (char *)pos + self->element_size,
|
||||||
|
((char *)self->end - self->element_size) - (char *)pos);
|
||||||
|
self->end = (char *)self->end - self->element_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayPushBack` ajoute un nouvel élément `elem` à l’objet `self` à la fin du
|
||||||
|
* tableau de ce dernier. Cette fonction modifie le membre `end` de `self`.
|
||||||
|
* \param self Objet \ref darray_t à la fin duquel on souhaite ajouter un nouvel élément
|
||||||
|
* \param elem Élément que l’on souhaite ajouter à la fin de `self`
|
||||||
|
*/
|
||||||
|
void darrayPushBack(darray_t *self, void *elem) {
|
||||||
|
darrayInsert(self, self->end, elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayPopBack` permet de supprimer le dernier élément de l’objet \ref
|
||||||
|
* darray_t passé en argument. Cette fonction modifie le membre `end` de ce
|
||||||
|
* dernier objet.
|
||||||
|
* \param self Objet dont on souhaite supprimer le dernier élément
|
||||||
|
*/
|
||||||
|
void darrayPopBack(darray_t *self) {
|
||||||
|
darrayErase(self, (char *)self->end - self->element_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayDelete` supprime tous les éléments contenus par l’objet \ref darray_t
|
||||||
|
* passé en argument avant de libérer la mémoire occupée par l’objet lui-même.
|
||||||
|
* L’objet passé en argument ne sera plus utilisable après utilisation de cette
|
||||||
|
* fonction.
|
||||||
|
* \param self Objet \ref darray_t à supprimer
|
||||||
|
*/
|
||||||
|
void darrayDelete(darray_t *self) {
|
||||||
|
free(self->begin);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darraySize` renvoie le nombre d’éléments contenu dans le \ref darray_t
|
||||||
|
* `self` passé en arguments. Cette fonction ne modifie pas l’élément passé en
|
||||||
|
* argument.
|
||||||
|
* \param self Objet \ref darray_t dont on souhaite connaître le nombre d’éléments
|
||||||
|
* \return Nombre d’éléments contenus dans `self`
|
||||||
|
*/
|
||||||
|
size_t darraySize(darray_t *self) {
|
||||||
|
return ((char *)self->end - (char *)self->begin) / self->element_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* `darrayGet` permet de récupérer un élément d’un objet \ref darray_t grâce à
|
||||||
|
* son index dans le tableau de l’objet `self`. Si l’index est trop grand, alors
|
||||||
|
* le pointeur `NULL` sera renvoyé, sinon un pointeur de type `void*` pointant
|
||||||
|
* sur l’élément correspondant sera renvoyé. Cette fonction ne modifie pas
|
||||||
|
* l’objet `self`.
|
||||||
|
* \param self Objet \ref darray_t duquel on souhaite obtenir un pointeur sur l’élément à l’index `idx`
|
||||||
|
* \param idx Index de l’élément que l’on souhaite récupérer
|
||||||
|
* \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 idx) {
|
||||||
|
void *itr;
|
||||||
|
itr = (char *)self->begin + idx * self->element_size;
|
||||||
|
return itr;
|
||||||
|
}
|
51
src/darray.h
Normal file
51
src/darray.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* \file darray.h
|
||||||
|
* \brief Implémentation de \ref darray_t et déclaration des fonctions pour ce type
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DARRAY_H
|
||||||
|
#define DARRAY_H
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \struct darray_t
|
||||||
|
* \brief Tableau dynamique
|
||||||
|
*
|
||||||
|
* Les objets `darray_t` offrent la possibilité d’avoir des tableaux à taille
|
||||||
|
* variable en C, similairement aux objets `vector` en C++.
|
||||||
|
*/
|
||||||
|
typedef struct darray_s {
|
||||||
|
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 (non destinée à l’utilisateur) */
|
||||||
|
} darray_t;
|
||||||
|
|
||||||
|
/// \brief Créé un nouvel objet \ref darray_t vide
|
||||||
|
darray_t *darrayNew(size_t element_size);
|
||||||
|
|
||||||
|
/// \brief Insère un élément à l’endroit pointé dans un \ref darray_t
|
||||||
|
void darrayInsert(darray_t *self, void *pos, void *elem);
|
||||||
|
|
||||||
|
/// \brief Supprime l’élément pointé dans l’objet \ref darray_t
|
||||||
|
void darrayErase(darray_t *self, void *pos);
|
||||||
|
|
||||||
|
/// \brief Retourne l’élément du \ref darray_t au idx-ème index
|
||||||
|
void *darrayGet(darray_t *self, size_t idx);
|
||||||
|
|
||||||
|
/// \brief Insère un élément à la fin de l’élément \ref darray_t
|
||||||
|
void darrayPushBack(darray_t *self, void *elem);
|
||||||
|
|
||||||
|
/// \brief Supprime le dernier élément de l’élément \ref darray_t
|
||||||
|
void darrayPopBack(darray_t *self);
|
||||||
|
|
||||||
|
/// \brief Détruit l’élément \ref darray_t
|
||||||
|
void darrayDelete(darray_t *self);
|
||||||
|
|
||||||
|
size_t darraySize(darray_t *self);
|
||||||
|
|
||||||
|
/// \brief Renvoie la taille de l’élément \ref darray_t
|
||||||
|
size_t darrayElemSize(darray_t *self);
|
||||||
|
|
||||||
|
#endif /* DARRAY_H */
|
216
src/ppm.c
Normal file
216
src/ppm.c
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* \file ppm.c
|
||||||
|
* \brief Fichier de déclaration des fonctions de manipulation d'images ppm
|
||||||
|
*
|
||||||
|
* Déclaration du corps des fonctions déclarées dans \ref ppm.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ppm.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define RGB_COMPONENT_COLOR 255
|
||||||
|
#define CREATOR "Cartier"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief function description
|
||||||
|
*
|
||||||
|
* Fonction d’ouverture de fichier selon le mode demandé. Si la fonction ne
|
||||||
|
* peut pas ouvrir le fichier, elle arrête le processus qui renverra la valeur
|
||||||
|
* `1`. En cas de succès, la fonction renverra un pointeur de fichier vers le
|
||||||
|
* fichier ouvert.
|
||||||
|
*
|
||||||
|
* \param[in] filename Nom du fichier à ouvrir
|
||||||
|
* \param[in] mode Mode du fichier à ouvrir
|
||||||
|
* \return Pointeur de fichier
|
||||||
|
*/
|
||||||
|
FILE* get_file(char *filename, const char* mode) {
|
||||||
|
FILE* fp = fopen(filename, mode);
|
||||||
|
if (!fp) {
|
||||||
|
fprintf(stderr, "Unable to open file '%s'\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lit et vérifie le format du fichier passé en argument. Si le format n’est
|
||||||
|
* pas correct, la fonction arrête le processus qui renverra la valeur `1`.
|
||||||
|
*
|
||||||
|
* \param[in] fb Fichier ppm où lire les données
|
||||||
|
* \param[in] filename Nom du fichier ouvert
|
||||||
|
*/
|
||||||
|
void read_file_format(FILE* fp, char* filename) {
|
||||||
|
char buff[16];
|
||||||
|
if (!fgets(buff, sizeof(buff), fp)) {
|
||||||
|
perror(filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* check file format */
|
||||||
|
if (buff[0] != 'P' || buff[1] != '6') {
|
||||||
|
fprintf(stderr, "Invalid image format (must be 'P6')\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie si le header contient des commentaires et les ignore le cas échéant.
|
||||||
|
*
|
||||||
|
* \param[in] fp Fichier ppm où lire les données
|
||||||
|
*/
|
||||||
|
void check_for_comments(FILE* fp) {
|
||||||
|
char c;
|
||||||
|
c = getc(fp);
|
||||||
|
while (c == '#') {
|
||||||
|
while (getc(fp) != '\n')
|
||||||
|
;
|
||||||
|
c = getc(fp);
|
||||||
|
}
|
||||||
|
ungetc(c, fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lit la taille des données image et les écrit dans le conteneur d’images
|
||||||
|
* passé en argument.
|
||||||
|
*
|
||||||
|
* \param[in] fp Fichier ppm où lire les données
|
||||||
|
* \param[out] img Conteneur d’image où écrire les résultats
|
||||||
|
* \param[in] filename Nom du fichier ouvert
|
||||||
|
*/
|
||||||
|
void read_file_size(FILE* fp, Image* img, char* filename) {
|
||||||
|
if (fscanf(fp, "%lu %lu", &img->x, &img->y) != 2) {
|
||||||
|
fprintf(stderr, "Invalid image size (error loading '%s')\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vérifie le format RGB de l’image ppm. Si le format n’est pas correct, la
|
||||||
|
* fonction arrête le processus qui renverra la valeur `1`.
|
||||||
|
*
|
||||||
|
* \param[in] fp Fichier ppm où lire les données
|
||||||
|
* \param[in] filename Nom du fichier ouvert
|
||||||
|
*/
|
||||||
|
void read_rgb(FILE* fp, char* filename) {
|
||||||
|
char d;
|
||||||
|
int rgb_comp_color;
|
||||||
|
/* read rgb component */
|
||||||
|
if (fscanf(fp, "%d", &rgb_comp_color) != 1) {
|
||||||
|
fprintf(stderr, "Invalid rgb component (error loading '%s')\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fscanf(fp, "%c ", &d);
|
||||||
|
/* check rgb component depth */
|
||||||
|
if (rgb_comp_color != RGB_COMPONENT_COLOR) {
|
||||||
|
fprintf(stderr, "'%s' does not have 8-bits components\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long read_data(FILE *fp, Image *img, GLubyte *data, char *filename) {
|
||||||
|
unsigned long size;
|
||||||
|
/* allocation memoire */
|
||||||
|
size = img->x * img->y * 3;
|
||||||
|
printf("Size image %lu %lu => %lu\n", img->x, img->y, size);
|
||||||
|
data = (GLubyte *)malloc((size_t)size * sizeof(GLubyte));
|
||||||
|
assert(data);
|
||||||
|
/* read pixel data from file */
|
||||||
|
if (!fread(data, (size_t)1, (size_t)size, fp)) {
|
||||||
|
fprintf(stderr, "Error loading image '%s'\n", filename);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convertit vers un tableau de `GLubyte` les pixels contenus dans un conteneur
|
||||||
|
* d’image. La taille du tableau de `GLubyte` est la taille du tableau de
|
||||||
|
* pixels multipliée par trois du fait des trois emplacements séparés par
|
||||||
|
* couleur.
|
||||||
|
*
|
||||||
|
* \param[out] img Image dont les pixels doivent être convertis
|
||||||
|
* \param[in] data Données à convertir en structures \ref Pixel
|
||||||
|
* \param[in] size Taille du tableau de `GLubyte`
|
||||||
|
* \return return type
|
||||||
|
*/
|
||||||
|
void dataToImage(Image *img, GLubyte *data, unsigned long size) {
|
||||||
|
unsigned long i;
|
||||||
|
img->pixels = darrayNew(sizeof(Pixel));
|
||||||
|
for (i = 0; i < size; i += 3) {
|
||||||
|
darrayPushBack(img->pixels, newPixel(data[i], data[i+1], data[i+2]));
|
||||||
|
darrayPushBack(img->pixels, newPixel(data[i], data[i+1], data[i+2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convertit le vecteur de pixels d’un conteneur d’image en un tableau de
|
||||||
|
* valeurs de type `GLuint` afin de permettre l’écriture d’une image dans un
|
||||||
|
* fichier.
|
||||||
|
*
|
||||||
|
* \param[in] img Conteneur d’image contenant les pixels à convertir
|
||||||
|
* \return Tableau de pointeurs de `GLuint`
|
||||||
|
*/
|
||||||
|
GLubyte *imageToData(Image_t img) {
|
||||||
|
Pixel_t pixel;
|
||||||
|
GLubyte *data, size;
|
||||||
|
unsigned long i;
|
||||||
|
size = darraySize(img->pixels);
|
||||||
|
data = (GLubyte *)malloc(3 * sizeof(GLubyte) * size);
|
||||||
|
for(i = 0; i < size; i += 3) {
|
||||||
|
pixel = darrayGet(img->pixels, i / 3);
|
||||||
|
data[i] = pixel->r;
|
||||||
|
data[i + 1] = pixel->g;
|
||||||
|
data[i + 2] = pixel->b;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ouvre le fichier image avec son nom de fichier passé par le paramètre
|
||||||
|
* `filename` et charge ses informations et données dans l'objet `img` dans
|
||||||
|
* lequel les données et l'image seront manipulables. Retourne la valeur 1 en
|
||||||
|
* cas de succès.
|
||||||
|
*
|
||||||
|
* \param[in] filename Nom du fichier image à ouvrir
|
||||||
|
* \param[out] img Objet \ref Image manipulable
|
||||||
|
* \return Retourne 1 en cas de succès
|
||||||
|
*/
|
||||||
|
int ImageLoadPPM(char *filename, Image *img) {
|
||||||
|
FILE *fp;
|
||||||
|
unsigned long size;
|
||||||
|
GLubyte* data = NULL;
|
||||||
|
fp = get_file(filename, "rb"); /* open PPM file for reading */
|
||||||
|
read_file_format(fp, filename); /* read image format */
|
||||||
|
check_for_comments(fp); /* check for comments */
|
||||||
|
read_file_size(fp, img, filename); /* read image size information */
|
||||||
|
read_rgb(fp, filename); /* read rgb component */
|
||||||
|
size = read_data(fp, img, data, filename); /* read data from file */
|
||||||
|
dataToImage(img, data, size);
|
||||||
|
fclose(fp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ouvre le fichier image avec son nom de fichier passé par le paramètre
|
||||||
|
* `filename` et y écrit les informations trouvées dans l’objet `img`.
|
||||||
|
*
|
||||||
|
* \param[in] filename Nom du fichier image à ouvrir
|
||||||
|
* \param[in] img Objet \ref Image à écrire
|
||||||
|
*/
|
||||||
|
void imagesavePPM(char *filename, Image_t img) {
|
||||||
|
FILE *fp;
|
||||||
|
GLubyte *data;
|
||||||
|
fp = get_file(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", img->y, img->y); /* image size */
|
||||||
|
fprintf(fp, "%d\n", RGB_COMPONENT_COLOR); /* rgb component depth */
|
||||||
|
data = imageToData(img); /* pixel data */
|
||||||
|
fwrite(data, (size_t)1, (size_t)(3 * img->x * img->y), fp);
|
||||||
|
free(data);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
36
src/ppm.h
Normal file
36
src/ppm.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* \file ppm.h
|
||||||
|
* \brief Fichier d'en-tête pour les fonctions de manipulation d'images ppm
|
||||||
|
*
|
||||||
|
* En-tête contenant la déclaration de fonctions de lecture et d'écriture de
|
||||||
|
* fichiers au format ppm. La définition des fonction se trouve dans \ref ppm.c
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMGTACHES_SRC_PPM_H_
|
||||||
|
#define IMGTACHES_SRC_PPM_H_
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
/// \brief Ouvre un fichier avec les autorisations demandées
|
||||||
|
FILE *get_file(char *filename, const char *mode);
|
||||||
|
/// \brief Lit le format d’un fichier ppm ouvert
|
||||||
|
void read_file_format(FILE* fp, char* filename);
|
||||||
|
/// \brief Vérifie et ignore d’éventuels commentaires du header d’un fichier
|
||||||
|
void check_for_comments(FILE *fp);
|
||||||
|
/// \brief Lit les dimensions du fichier ppm ouvert
|
||||||
|
void read_file_size(FILE *fp, Image *img, char *filename);
|
||||||
|
/// \brief Lit et vérifie le format RGB du fichier ppm
|
||||||
|
void read_rgb(FILE *fp, char *filename);
|
||||||
|
/// \brief Lit dans le conteneur les données images du fichier ppm
|
||||||
|
unsigned long read_data(FILE *fp, Image *img, GLubyte *data, char *filename);
|
||||||
|
/// \brief Convertit les données brutes de fichier vers des conteneurs de pixels
|
||||||
|
void dataToImage(Image *img, GLubyte *data, unsigned long size);
|
||||||
|
/// \brief Convertit les pixels d’une image en tableau natif OpenGL
|
||||||
|
GLubyte *imageToData(Image_t img);
|
||||||
|
/// \brief Ouverture et lecture de l’image d’entrée
|
||||||
|
int ImageLoadPPM(char *filename, Image_t img);
|
||||||
|
/// \brief Ouverture et écriture de l'image de sortie
|
||||||
|
void imagesavePPM(char *filename, Image_t img);
|
||||||
|
|
||||||
|
#endif /* IMGTACHES_SRC_PPM_H_ */
|
143
src/utilities.c
Normal file
143
src/utilities.c
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
/**
|
||||||
|
* \file utilities.c
|
||||||
|
* \brief Implémentation des fonctions utilitaires
|
||||||
|
*
|
||||||
|
* Dans ce fichier sont implémentées les fonctions utilitaires pour la
|
||||||
|
* manipulation des structures de données déclarées dans le fichier header
|
||||||
|
* correspondant.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utilities.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Créé un nouveau pixel initialisé avec les arguments `r`, `g` et `b` et
|
||||||
|
* renvoie un pointeur vers ce pixel créé.
|
||||||
|
*
|
||||||
|
* \param[in] r Valeur rouge du pixel
|
||||||
|
* \param[in] g Valeur verte du pixel
|
||||||
|
* \param[in] b Valeur bleue du pixel
|
||||||
|
* \return Pointeur sur une structure de type \ref Pixel
|
||||||
|
*/
|
||||||
|
Pixel_t newPixel(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
Pixel_t res;
|
||||||
|
res = (Pixel_t)malloc(sizeof(Pixel));
|
||||||
|
res->r = r;
|
||||||
|
res->g = g;
|
||||||
|
res->b = b;
|
||||||
|
res->visited = false;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur d’un pixel. Étant donné qu’un pixel ne contient aucune donnée
|
||||||
|
* pointée par un pointeur, la seule action de la fonction sera de libérer la
|
||||||
|
* mémoire pointée par le pointeur de pixel en lui-même et donc le pixel passé
|
||||||
|
* en argument.
|
||||||
|
*
|
||||||
|
* \param[in] self Pointeur vers le pixel à détruire
|
||||||
|
*/
|
||||||
|
void deletePixel(Pixel_t self) {
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur d’un conteneur d’image. Les dimensions sont initialisées à zéro
|
||||||
|
* (0) et son tableau de pixels a été créé et initialisé en tableau vide. Le
|
||||||
|
* constructeur renvoie un pointeur vers la nouvelle structure \ref Image.
|
||||||
|
*
|
||||||
|
* \return Pointeur vers une structure \ref Image initialisée.
|
||||||
|
*/
|
||||||
|
Image_t newImage() {
|
||||||
|
Image_t res;
|
||||||
|
res = (Image_t)malloc(sizeof(Image));
|
||||||
|
res->x = 0;
|
||||||
|
res->y = 0;
|
||||||
|
res->pixels = darrayNew(sizeof(Pixel));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur d’un conteneur d’image. Le destructeur appellera le destructeur
|
||||||
|
* du vecteur de pixels qui sera libéré de la mémoire, puis ultimement le
|
||||||
|
* destructeur libérera la structure \ref Image pointée par le pointeur passé
|
||||||
|
* en argument.
|
||||||
|
*
|
||||||
|
* \param[in] self Conteneur d’image à détruire
|
||||||
|
*/
|
||||||
|
void deleteImage(Image_t self) {
|
||||||
|
unsigned long i;
|
||||||
|
for(i = 0; i < darraySize(self->pixels); ++i) {
|
||||||
|
deletePixel(darrayGet(self->pixels, i));
|
||||||
|
}
|
||||||
|
darrayDelete(self->pixels);
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur d’un conteneur de segment. Le constructeur va initialiser les
|
||||||
|
* valeurs qu’il contiendra avec les arguments qui lui seront passés lors de
|
||||||
|
* l’appel de la fonction.
|
||||||
|
*
|
||||||
|
* \param[in] y Ordonnée à laquelle le segment réside
|
||||||
|
* \param[in] xd Abscisse extrême droite du segment
|
||||||
|
* \param[in] xg Abscisse extrême gauche du segment
|
||||||
|
* \return Pointeur sur un conteneur de segment
|
||||||
|
*/
|
||||||
|
Segment_t newSegment(uint64_t y, uint64_t xd, uint64_t xg) {
|
||||||
|
Segment_t res;
|
||||||
|
res = (Segment_t)malloc(sizeof(Segment));
|
||||||
|
res->y = y;
|
||||||
|
res->xd = xd;
|
||||||
|
res->xg = xg;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur de conteneur de segment. Les conteneurs de segments ne contenant
|
||||||
|
* pas de pointeur propriétaire de données, le destructeur libérera simplement
|
||||||
|
* de la mémoire le conteneur pointé par le pointeur passé en argument.
|
||||||
|
*
|
||||||
|
* \param[in] self Conteneur de segment à détruire
|
||||||
|
*/
|
||||||
|
void deleteSegment(Segment_t self) {
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief function description
|
||||||
|
*
|
||||||
|
* Constructeur de conteneur de zone, initialise grâce aux arguments la couleur
|
||||||
|
* de la zone et initialise un tableau dynamique vide de \ref Segment. Renvoie
|
||||||
|
* un pointeur vers la structure nouvellement créée.
|
||||||
|
*
|
||||||
|
* \param[in] r Valeur rouge de la couleur de la zone
|
||||||
|
* \param[in] g Valeur verte de la couleur de la zone
|
||||||
|
* \param[in] b Valeur bleue de la couleur de la zone
|
||||||
|
* \return Pointeur vers la structure créée
|
||||||
|
*/
|
||||||
|
Zone_t newZone(uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
Zone_t res;
|
||||||
|
res = (Zone_t)malloc(sizeof(Zone));
|
||||||
|
res->r = r;
|
||||||
|
res->g = g;
|
||||||
|
res->b = b;
|
||||||
|
res->segments = darrayNew(sizeof(Segment));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructeur de zone, libère de la mémoire les segments contenus dans le
|
||||||
|
* tableau de segments, puis le tableau en lui-même pour ultimement libérer
|
||||||
|
* de la mémoire le conteneur de zone en lui-même pointé par le pointeur passé
|
||||||
|
* en argument du destructeur.
|
||||||
|
*
|
||||||
|
* \param[in] self Conteneur de zone à détruire
|
||||||
|
*/
|
||||||
|
void deleteZone(Zone_t self) {
|
||||||
|
unsigned long i;
|
||||||
|
for(i = 0; i < darraySize(self->segments); ++i) {
|
||||||
|
deleteSegment(darrayGet(self->segments, i));
|
||||||
|
}
|
||||||
|
darrayDelete(self->segments);
|
||||||
|
free(self);
|
||||||
|
}
|
131
src/utilities.h
Normal file
131
src/utilities.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/**
|
||||||
|
* \file utilities.h
|
||||||
|
* \brief Déclaraction des structures de données et fonctions utilitaires.
|
||||||
|
*
|
||||||
|
* Dans ce fichier sont déclarées et implémentées les structures qui serviront
|
||||||
|
* de conteneurs aux données manipulées. Sont également déclarées les fonctions
|
||||||
|
* utilitaires pour la manipulation de ces structures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UTILITIES_H
|
||||||
|
#define UTILITIES_H
|
||||||
|
|
||||||
|
#include "darray.h"
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* DEFINE DIRECTIVES */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef Debug
|
||||||
|
#define DEBUG if (1)
|
||||||
|
#define PDEB \
|
||||||
|
if (1) \
|
||||||
|
printf
|
||||||
|
#else
|
||||||
|
#define DEBUG if (0)
|
||||||
|
#define PDBEF \
|
||||||
|
if (0) \
|
||||||
|
printf
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* STRUCT DECLARATION */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
struct Image;
|
||||||
|
typedef struct Image Image;
|
||||||
|
typedef Image *Image_t;
|
||||||
|
struct Pixel;
|
||||||
|
typedef struct Pixel Pixel;
|
||||||
|
typedef Pixel *Pixel_t;
|
||||||
|
struct Zone;
|
||||||
|
typedef struct Zone Zone;
|
||||||
|
typedef Zone *Zone_t;
|
||||||
|
struct Segment;
|
||||||
|
typedef struct Segment Segment;
|
||||||
|
typedef Segment *Segment_t;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* STRUCT IMPLEMENTATION */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Conteneur d’une image
|
||||||
|
*
|
||||||
|
* Une image est une structure définie par ses dimensions verticales et
|
||||||
|
* horizontales x et y, et contenant pour chacune des coordonnées possibles
|
||||||
|
* selon ses dimensions un pixel de type \ref Pixel. Ces pixels sont stockés
|
||||||
|
* dans un tableau dynamique \ref darray_t.
|
||||||
|
*/
|
||||||
|
struct Image {
|
||||||
|
uint64_t x; /*!< Largeur de l’image */
|
||||||
|
uint64_t y; /*!< Hauteur de l’image */
|
||||||
|
darray_t *pixels; /*!< Vecteur de pixels */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Conteneur d’un pixel
|
||||||
|
*
|
||||||
|
* Un pixel est défini par sa couleur représenté en RGB (rouge, vert, bleu).
|
||||||
|
* Il contient également une valeur booléenne afin de savoir si le Pixel fut
|
||||||
|
* 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 */
|
||||||
|
bool visited; /*!< Le pixel a-t-il été visité avant */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Conteneur de zone de couleur unie
|
||||||
|
*
|
||||||
|
* Une zone est un ensemble de pixels de même couleur ou de couleur similaire
|
||||||
|
* 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_t *segments; /*!< Vecteur de segments */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Conteneur de segment de couleur unie
|
||||||
|
*
|
||||||
|
* Un segment est un ensemble de pixels de même ordonnée et de couleur unie ou
|
||||||
|
* similaire. Il se définit par son ordonnée y et de ses deux pixels de bordure
|
||||||
|
* à son extrême droite et à son extrême gauche.
|
||||||
|
*/
|
||||||
|
struct Segment {
|
||||||
|
uint16_t y; /*!< ligne du segment */
|
||||||
|
uint16_t xd; /*!< extrême droit du segment */
|
||||||
|
uint16_t xg; /*!< extrême gauche du segment */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Utility functions declaration */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/// \brief Création d’un nouveau pixel
|
||||||
|
Pixel_t newPixel(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
/// \brief Destruction d’un pointeur de pixel
|
||||||
|
void deletePixel(Pixel_t self);
|
||||||
|
/// \brief Création d’une nouvelle image
|
||||||
|
Image_t newImage();
|
||||||
|
/// \brief Destructeur d’une image
|
||||||
|
void deleteImage(Image_t self);
|
||||||
|
/// \brief Constructeur d’un segment de couleur unie
|
||||||
|
Segment_t newSegment(uint64_t y, uint64_t xd, uint64_t xg);
|
||||||
|
/// \brief Destructeur d’un segment de couleur unie
|
||||||
|
void deleteSegment(Segment_t self);
|
||||||
|
/// \brief Constructeur de conteneur de zone
|
||||||
|
Zone_t newZone(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
/// \brief Destructeur de conteneur de zone
|
||||||
|
void deleteZone(Zone_t self);
|
||||||
|
|
||||||
|
#endif /* UTILITIES_H */
|
Loading…
Reference in New Issue
Block a user