diff --git a/Matrix.c b/Matrix.c index 820cd2595bf12da799fea159c584f7c40ea5a09c..51200384fcbaed64b45969a202aeafa5a3db3f8d 100644 --- a/Matrix.c +++ b/Matrix.c @@ -55,7 +55,7 @@ error_code matrix_destroy(matrix *mat){ for (int i = 0; i < mat->col; i++){ for(int j=0;j<mat->lin;j+=1) { - mat->data[i][j] = NULL; + mat->data[i][j] = 0; } free(mat->data[i]); } diff --git a/main.c b/main.c index dad4f0b1cca1115d4ed61672d7b033ed5a764ad2..30336b09916f81cfd8063d96ab2f07bcebcf919d 100644 --- a/main.c +++ b/main.c @@ -16,31 +16,27 @@ int main() printf("Depth : %u\n",val); - // matrix_print(p->pixels); node* tree = quadtree_tree_create(val); - - // matrix_print(p->pixels); quadtree_matrix2tree(&p->pixels,tree); pgm* pp = malloc(1 * sizeof(pgm)); pp->max = p->max; matrix_alloc(&pp->pixels,p->pixels.lin,p->pixels.col); - // matrix mat; - // matrix_alloc(&mat,p->pixels.lin,p->pixels.col); - // matrix_init(&mat); - quadtree_central_symetry(tree); + + + + + quadtree_moyenne(tree); + quadtree_compress(tree,2000); + + // quadtree_print(tree,1,"|"); quadtree_tree2matrix(tree,&pp->pixels); - // // matrix_print(mat); - // // quadtree_print(tree,1,"|"); - // pgm *pp = malloc(1 * sizeof(pgm)); - // pp->max = 256; - // pp->pixels = mat; - pgm_write_from_file(pp,"Test.pgm"); + pgm_write_from_file(pp,"Test.pgm"); matrix_destroy(&p->pixels); matrix_destroy(&pp->pixels); quadtree_tree_destroy(&tree); diff --git a/pgm_io.c b/pgm_io.c index 7d67a0e0c81a218ff157e765393b0ae1cc4ce6c7..887b7b7cd4bebe9c99226857736e5c4413820c31 100644 --- a/pgm_io.c +++ b/pgm_io.c @@ -14,7 +14,7 @@ * @param filename = the file path of the image to read * @return pgm_error */ -pgm_error pgm_read_from_file(pgm *p,const char* const filename) +pgm_error pgm_read_from_file(pgm *p,const char* filename) { int sizex = 0; int sizey = 0; @@ -56,7 +56,7 @@ pgm_error pgm_read_from_file(pgm *p,const char* const filename) * @param filename = the file path of the image to write * @return pgm_error */ -pgm_error pgm_write_from_file(pgm *p,char *filename) +pgm_error pgm_write_from_file(pgm *p,const char *filename) { if (p->pixels.data == NULL) { @@ -127,7 +127,7 @@ pgm_error pgm_duplicate(char *filename,char *newfile) * @param gray_scale = the gray scale max in file returned by pointed value * @return pgm_error */ -pgm_error pgm_read_header(const char* const filename,int *sizex,int *sizey,int *gray_scale) +pgm_error pgm_read_header(const char* filename,int *sizex,int *sizey,int *gray_scale) { FILE *f; f = fopen(filename,"r"); diff --git a/pgm_io.h b/pgm_io.h index 7b99628e593cbea01360f650c57fde3176fdbf7a..08370db557bc8696a852922e9b7125c28f7391c6 100644 --- a/pgm_io.h +++ b/pgm_io.h @@ -18,9 +18,9 @@ int32_t max; matrix pixels; } pgm; -pgm_error pgm_read_from_file(pgm *p,const char* const filename); -pgm_error pgm_write_from_file(pgm *p,char *filename); +pgm_error pgm_read_from_file(pgm *p,const char* filename); +pgm_error pgm_write_from_file(pgm *p,const char *filename); pgm_error pgm_duplicate(char *filename,char *newfile); -pgm_error pgm_read_header(const char* const filename,int *sizex,int *sizey,int *gray_scale); +pgm_error pgm_read_header(const char* filename,int *sizex,int *sizey,int *gray_scale); #endif \ No newline at end of file diff --git a/quadtree.c b/quadtree.c index 2246883624df0d8754b294ba509f979fb3af49a7..013058d619c6902acba0b8d1431ad4bc8ff77393 100644 --- a/quadtree.c +++ b/quadtree.c @@ -1,15 +1,33 @@ #include "quadtree.h" +/** + * @name quadtree_is_leaf + * @brief Check if this node is a leaf + * @param nd ptr on node + * @return true if it is a leaf + */ bool quadtree_is_leaf(node *nd) { return (NULL == nd->child[0]); } +/** + * @name quadtree_get_depth_from_image_size + * @brief Get depth from size of image (square only) + * @param sizex value of border + * @return value of depth + */ int32_t quadtree_get_depth_from_image_size(int32_t sizex) { return (int32_t)log2(sizex); } +/** + * @name quadtree_tree_create + * @brief Create quadtree from depth + * @param depth value of depth for the quadtree + * @return pointer on node for quadtree + */ node *quadtree_tree_create(int32_t depth) { node *a = calloc(1, sizeof(node)); @@ -24,11 +42,25 @@ node *quadtree_tree_create(int32_t depth) return a; } +/** + * @name quadtree_max + * @brief Compare two value + * @param x first value + * @param y second value + * @return the greatest value betwen x and y + */ int32_t quadtree_max(int32_t x, int32_t y) { return (x >= y ? x : y); } +/** + * @name quadtree_array_max + * @brief Get max value in array + * @param size size of array + * @param tab the array + * @return the bigest value oin the array + */ int32_t quadtree_array_max(int32_t size, int32_t tab[size]) { int32_t m = INT_MIN; @@ -39,10 +71,16 @@ int32_t quadtree_array_max(int32_t size, int32_t tab[size]) return m; } -int32_t quadtree_depth(node *a) +/** + * @name quadtree_depth + * @brief Get the depth of quadtree + * @param a pointer on node + * @return the value of depth quadtree + */ +int32_t quadtree_depth(node *tree) { int32_t p[CHILDREN] = {0}; - if (quadtree_is_leaf(a)) + if (quadtree_is_leaf(tree)) { return 0; } @@ -50,33 +88,47 @@ int32_t quadtree_depth(node *a) { for (int32_t i = 0; i < CHILDREN; i++) { - p[i] = 1 + quadtree_depth(a->child[i]); + p[i] = 1 + quadtree_depth(tree->child[i]); } return quadtree_array_max(CHILDREN, p); } } -void quadtree_print(node *arbre, int32_t decal, char *sep) +/** + * @name quadtree_print + * @brief Print all value in quadtree + * @param tree pointer on node + * @param decal value of additional char + * @param sep char to use for graphic display + * @return void + */ +void quadtree_print(node *tree, int32_t decal, char *sep) { - if (NULL != arbre) + if (NULL != tree) { for (int32_t i = 0; i < decal; i++) { printf("%s", sep); } - printf("%d\n", (uint32_t)arbre->data); + printf("%lf\n", tree->average); decal++; - if (!quadtree_is_leaf(arbre)) + if (!quadtree_is_leaf(tree)) { for (int32_t i = 0; i < CHILDREN; i++) { - quadtree_print(arbre->child[i], decal, sep); + quadtree_print(tree->child[i], decal, sep); } } } } -// Fonction utile pour les symétries +/** + * @name quadtree_swap + * @brief Swap two pointer + * @param ptr1 pointer of pointer on void + * @param ptr2 pointer of pointer on void + * @return void + */ void quadtree_swap(void **ptr1, void **ptr2) { void *tmp = *ptr1; @@ -84,64 +136,79 @@ void quadtree_swap(void **ptr1, void **ptr2) *ptr2 = tmp; } -void quadtree_sum(node *arbre) +/** + * @name quadtree_sum + * @brief Sum of all value in tree + * @param tree pointer on node + * @return void + */ +void quadtree_sum(node *tree) { - if (!quadtree_is_leaf(arbre)) + if (!quadtree_is_leaf(tree)) { for (int32_t i = 0; i < CHILDREN; i++) { - quadtree_sum(arbre->child[i]); + quadtree_sum(tree->child[i]); } for (int32_t i = 0; i < CHILDREN; i++) { - arbre->data += arbre->child[i]->data; + tree->average += tree->child[i]->average; } } } -node *quadtree_position(int32_t li, int32_t col, node *a, int32_t d) +/** + * @name quadtree_position + * @brief Get node from position in quadtree + * @param li line number + * @param col colone number + * @param tree pointer on node + * @param depth depth value + * @return pointer on node + */ +node *quadtree_position(int32_t li, int32_t col, node *tree, int32_t depth) { - node *crt = a; + node *crt = tree; do { - int32_t ligne = (li >> d) & 1; // Permet de sélectionne le bit à considérer en fonction de la profondeur; Exemple: 10 >> 1 = 1 - int32_t colonne = (col >> d) & 1; //Exemple: 10 >> 1 = 1; - int32_t index = (ligne << 1) | colonne; // Exemple: 1<<1 = 10 | 1(col) = 11=>3 + int32_t ligne = (li >> depth) & 1; + int32_t colonne = (col >> depth) & 1; + int32_t index = (ligne << 1) | colonne; crt = crt->child[index]; - d--; + depth--; } while (!quadtree_is_leaf(crt)); return crt; } -double quadtree_position_value(int32_t li, int32_t col, node *a, int32_t d) -{ - node *crt = a; - do - { - int32_t ligne = (li >> d) & 1; // Permet de sélectionne le bit à considérer en fonction de la profondeur; Exemple: 10 >> 1 = 1 - int32_t colonne = (col >> d) & 1; //Exemple: 10 >> 1 = 1; - int32_t index = (ligne << 1) | colonne; // Exemple: 1<<1 = 10 | 1(col) = 11=>3 - - crt = crt->child[index]; - d--; - } while (!quadtree_is_leaf(crt)); - return crt->data; -} - -void quadtree_matrix2tree(matrix *mat, node *arbre) +/** + * @name quadtree_matrix2tree + * @brief Convert matrix to quadtree + * @param mat pointer on matrix + * @param tree pointer on node + * @return void + */ +void quadtree_matrix2tree(matrix *mat, node *tree) { - int32_t d = quadtree_depth(arbre) - 1; + int32_t d = quadtree_depth(tree) - 1; for (int32_t li = 0; li < mat->lin; li++) { for (int32_t co = 0; co < mat->col; co++) { - node *crt = quadtree_position(li, co, arbre, d); - crt->data = mat->data[li][co]; + node *crt = quadtree_position(li, co, tree, d); + crt->average = mat->data[li][co]; + crt->average_2 = mat->data[li][co] * mat->data[li][co]; } } } +/** + * @name quadtree_tree2matrix + * @brief Convert quadtree to matrix + * @param tree pointer on node + * @param mat pointer on matrix + * @return void + */ void quadtree_tree2matrix(node *tree, matrix *mat) { int32_t d = quadtree_depth(tree) - 1; @@ -149,12 +216,17 @@ void quadtree_tree2matrix(node *tree, matrix *mat) { for (int32_t co = 0; co < mat->col; co++) { - mat->data[li][co] = quadtree_position_value(li, co, tree, d); + mat->data[li][co] = quadtree_position(li, co, tree, d)->average; } } } -// OK +/** + * @name quadtree_horizontal_symetry + * @brief Apply rotate on branch in quadtree for horizontal symmetry + * @param tree pointer on node + * @return void + */ void quadtree_horizontal_symetry(node *tree) { if (NULL != tree) @@ -163,12 +235,17 @@ void quadtree_horizontal_symetry(node *tree) { quadtree_horizontal_symetry(tree->child[i]); } - quadtree_swap((void**)&tree->child[0], (void**)&tree->child[1]); - quadtree_swap((void**)&tree->child[2], (void**)&tree->child[3]); + quadtree_swap((void **)&tree->child[0], (void **)&tree->child[1]); + quadtree_swap((void **)&tree->child[2], (void **)&tree->child[3]); } } -// OK +/** + * @name quadtree_vertical_symetry + * @brief Apply rotate on branch in quadtree for vertical symmetry + * @param tree pointer on node + * @return void + */ void quadtree_vertical_symetry(node *tree) { if (NULL != tree) @@ -177,17 +254,29 @@ void quadtree_vertical_symetry(node *tree) { quadtree_vertical_symetry(tree->child[i]); } - quadtree_swap((void**)&tree->child[0], (void**)&tree->child[2]); - quadtree_swap((void**)&tree->child[1], (void**)&tree->child[3]); + quadtree_swap((void **)&tree->child[0], (void **)&tree->child[2]); + quadtree_swap((void **)&tree->child[1], (void **)&tree->child[3]); } } +/** + * @name quadtree_central_symetry + * @brief Apply rotate on branch in quadtree for central symmetry + * @param tree pointer on node + * @return void + */ void quadtree_central_symetry(node *tree) { quadtree_vertical_symetry(tree); quadtree_horizontal_symetry(tree); } +/** + * @name quadtree_tree_destroy + * @brief Destroy all memory alloc from quadtree_create + * @param tree pointer on pointer on node + * @return void + */ void quadtree_tree_destroy(node **tree) { if (NULL != *tree) @@ -204,4 +293,69 @@ void quadtree_tree_destroy(node **tree) free(*tree); } } +} + +/** + * @name quadtree_moyenne + * @brief Write moyenn of sub branch in node + * @param tree pointer on node + * @return void + */ +void quadtree_moyenne(node *tree) +{ + if (!quadtree_is_leaf(tree)) + { + for (uint32_t i = 0; i < CHILDREN; i += 1) + { + quadtree_moyenne(tree->child[i]); + } + tree->average = 0.0; + tree->average_2 = 0.0; + for (uint32_t i = 0; i < CHILDREN; i += 1) + { + tree->average += tree->child[i]->average; + tree->average_2 += tree->child[i]->average_2; + } + tree->average /= CHILDREN; + tree->average_2 /= CHILDREN; + } +} + +/** + * @name quadtree_compress + * @brief Compress data in quadtree + * @param tree pointer on node + * @param level compression ratio + * @return void + */ +void quadtree_compress(node *tree, uint32_t level) +{ + if (!quadtree_is_leaf(tree)) + { + for (uint32_t i = 0; i < CHILDREN; i += 1) + { + quadtree_compress(tree->child[i], level); + } + bool last_branch = true; + for (uint32_t i = 0; i < CHILDREN; i += 1) + { + if (!quadtree_is_leaf(tree->child[i])) + { + last_branch = false; + } + } + if (last_branch) + { + double tmp_var = tree->average_2 - (tree->average * tree->average); + if (tmp_var <= level) + { + tree->average = (uint32_t)(tree->average); + for (uint32_t i = 0; i < CHILDREN; i += 1) + { + free(tree->child[i]); + tree->child[i] = NULL; + } + } + } + } } \ No newline at end of file diff --git a/quadtree.h b/quadtree.h index 22d3fa953c1049e1844da564d5797fbd88ca7bc5..78acb56390cc482762acc8fad28243b8dd58f8fa 100644 --- a/quadtree.h +++ b/quadtree.h @@ -10,7 +10,7 @@ #define CHILDREN 4 typedef struct _node { - double data; + double average; double average_2; struct _node* child[CHILDREN]; } node; @@ -49,4 +49,8 @@ void quadtree_horizontal_symetry(node *tree); void quadtree_vertical_symetry(node *tree); -void quadtree_central_symetry(node *tree); \ No newline at end of file +void quadtree_central_symetry(node *tree); + +void quadtree_compress(node* tree,uint32_t level); + +void quadtree_moyenne(node* tree); \ No newline at end of file