/* images_processing.cpp */#include <iostream>#include "images_processing.h"using namespace std;struct Pixel { int R, G, B;};/* Fonction qui applique un filtre linéaire à l'image. Elle prend en paramètre l'adresse du pointeur vers le tableau, la matrice deconvolution, la longueur et la largeur du tableau */struct Pixel ** apply_linear_filter(Pixel ** array, float mat_convol[7][7], int width, int height) { int i, j; float new_pixel_val_R, new_pixel_val_G, new_pixel_val_B; // On crée un nouveau tableau de la même taille que le précédent pour y stocker les nouvelles valeurs des pixels Pixel **array_ter = new Pixel *[height]; for(i = 0; i < height; i++) { array_ter[i] = new Pixel [width]; } // On parcourt tout le tableau for(i = 0; i < height; i++) { for(j = 0; j < width; j++) { // On met les valeurs des nouveaux pixels à zéros new_pixel_val_R = 0.0; new_pixel_val_G = 0.0; new_pixel_val_B = 0.0; // On parcourt la matrice de convolution ainsi que les éléments du tableau qui seront affectés par la matrice // Voir schéma n° x for(int i_1 = -3; i_1 <= 3; i_1++) { for(int j_1 = -3; j_1 <= 3; j_1++) { if(i + i_1 >= 0 && i + i_1 < height && j + j_1 >= 0 && j + j_1 < width) { new_pixel_val_R += mat_convol[3 + i_1][3 + j_1] * float(array[i + i_1][j + j_1].R); new_pixel_val_G += mat_convol[3 + i_1][3 + j_1] * float(array[i + i_1][j + j_1].G); new_pixel_val_B += mat_convol[3 + i_1][3 + j_1] * float(array[i + i_1][j + j_1].B); } } } // On vérifie que la valeur des pixels n'est pas négative ou positive auxquels cas, on rectifie if(new_pixel_val_R > 255) new_pixel_val_R = 255; else if(new_pixel_val_R < 0) new_pixel_val_R = 0; if(new_pixel_val_G > 255) new_pixel_val_G = 255; else if(new_pixel_val_G < 0) new_pixel_val_G = 0; if(new_pixel_val_B > 255) new_pixel_val_B = 255; else if(new_pixel_val_B < 0) new_pixel_val_B = 0; // On ajoute ces valeurs arrondies à l'entier inférieur dans la nouvelle matrice array_ter[i][j].R = int(new_pixel_val_R); array_ter[i][j].G = int(new_pixel_val_G); array_ter[i][j].B = int(new_pixel_val_B); } } // On supprime l'ancien tableau devenu inutile for(i = 0; i < height; i++) { delete[] array[i]; } delete[] array; // On renvoie l'adresse du nouveau tableau pour faire pointer le pointeur défini dans main dessus return array_ter;}// Fonction de tri par sélectionvoid selection_sort(int array_sort[], const int length) { int i, j, max, max_pos, tmp; for(i = length - 1; i >= 0; i--) { max = array_sort[0]; max_pos = 0; for(j = 1; j < i; j++) { if(max < array_sort[j]) { max = array_sort[j]; max_pos = j; } } tmp = array_sort[i]; array_sort[i] = max; array_sort[max_pos] = tmp; }}/* Fonction qui applique un filtre non-linéaire à l'image. Elle prend en paramètre l'adresse du pointeur vers le tableau, la longueur et la largeur du tableau */struct Pixel ** apply_non_linear_filter(Pixel ** array, int width, int height) { int i, j, i_1, j_1, k; // On crée un nouveau tableau de la même taille que le précédent pour y stocker les nouvelles valeurs des pixels Pixel **array_ter = new Pixel *[height]; for(i = 0; i < height; i++) { array_ter[i] = new Pixel [width]; } // On parcourt tout le tableau for(i = 0; i < height; i++) { for(j = 0; j < width; j++) { int array_2_sort_R[9], array_2_sort_G[9], array_2_sort_B[9]; k = 0; /* Ici on use d'une astuce qui simule une sorte de matrice carrée centrée sur l'élément courant pour parcourir tous les éléments autour. De plus, on use de l'effet miroir, c-à-d qu'au lieu de considére les pixels au-delà du bord comme étant égaux à 0, on fait une symétrie centrale par rapport à l'élement courant */ for(i_1 = -1; i_1 <= 1; i_1++) { for(j_1 = -1; j_1 <= 1; j_1++) { if(i + i_1 < 0 || i + i_1 > height - 1) { if(j + j_1 < 0 || j + j_1 > width - 1) { array_2_sort_R[k] = array[i - i_1][j - j_1].R; array_2_sort_G[k] = array[i - i_1][j - j_1].G; array_2_sort_B[k] = array[i - i_1][j - j_1].B; } else { array_2_sort_R[k] = array[i - i_1][j + j_1].R; array_2_sort_G[k] = array[i - i_1][j + j_1].G; array_2_sort_B[k] = array[i - i_1][j + j_1].B; } } else { if(j + j_1 < 0 || j + j_1 > width - 1) { array_2_sort_R[k] = array[i + i_1][j - j_1].R; array_2_sort_G[k] = array[i + i_1][j - j_1].G; array_2_sort_B[k] = array[i + i_1][j - j_1].B; } else { array_2_sort_R[k] = array[i + i_1][j + j_1].R; array_2_sort_G[k] = array[i + i_1][j + j_1].G; array_2_sort_B[k] = array[i + i_1][j + j_1].B; } } k++; } } // On trie le tableau qui contient l'ensemble des pixels autour du pixel central selection_sort(array_2_sort_R, 9); selection_sort(array_2_sort_G, 9); selection_sort(array_2_sort_B, 9); // On prend l'élément du milieu array_ter[i][j].R = array_2_sort_R[4]; array_ter[i][j].G = array_2_sort_G[4]; array_ter[i][j].B = array_2_sort_B[4]; } } // On supprime l'ancien tableau devenu inutile for(i = 0; i < height; i++) { delete[] array[i]; } delete[] array; // On renvoie l'adresse du nouveau tableau pour faire pointer le pointeur défini dans main dessus return array_ter;}/* Fonction qui réduit une image. Elle prend en paramètre l'adresse du pointeur vers le tableau, la longueur et la largeur du tableau et lepourcentage de réduction.L'idée est de faire la moyenne d'un certain nombre de pixels (calculé en fonction du pourcentage de réduction) et de stocker cette valeurdans un nouveau pixel */struct Pixel ** shrink_image(Pixel ** array, int & width, int & height, float percent) { /* Liste des variables entières: new_width est la nouvelle largeur du tableau arrondie à l'unité inférieure new_height est la nouvelle hauteur du tableau arrondie à l'unité inférieure height_inc est l'incrémentation de hauteur, c-à-d le nombre d'éléments en hauteur qui vont être "compressés" dans un seul pixel width_inc est l'incrémentation de largeur, c-à-d le nombre d'éléments en largeur qui vont être "compressés" dans un seul pixel i parcourt les lignes du tableau j parcourt les colonnes du tableau i_1 parcourt les lignes de la zone à "compresser" j_1 parcourt les colonnes de la zone à "compresser" count compte le nombre d'éléments pour la division dans le calcul de la moyenne (par ex: sum_R / count) cur_new_i représente l'indice de ligne du pixel vers lequel sera "compressée" la zone courante cur_new_j représente l'indice de colonne du pixel vers lequel sera "compressée" la zone courante */ int new_width = int(float(1.0 * width * percent)), new_height = int(float(1.0 * height * percent)), height_inc, width_inc; int i, j, i_1, j_1, count, cur_new_i = 0, cur_new_j = 0, pixels_left_height, pixels_left_width; /* Liste des variables float: ratio_height contient le quotient de la hauteur originale et de la nouvelle hauteur pour pouvoir calculer la hauteur de la zone à compresser ratio_width contient le quotient de la largeur originale et de la nouvelle largeur pour pouvoir calculer la largeur de la zone à compresser sum_R contient la somme des valeurs des pixels rouges pour le calcul de la moyenne (sum_R / count) sum_G contient la somme des valeurs des pixels verts pour le calcul de la moyenne (sum_R / count) sum_B contient la somme des valeurs des pixels bleus pour le calcul de la moyenne (sum_R / count) */ float ratio_height = 1.0 * height / new_height, ratio_width = 1.0 * width / new_width, sum_R, sum_G, sum_B; // On crée un nouveau tableau de la nouvelle taille pour y stocker les nouvelles valeurs des pixels Pixel **array_ter = new Pixel *[new_height]; for(i = 0; i < new_height; i++) { array_ter[i] = new Pixel [new_width]; } height_inc = int(ratio_height); width_inc = int(ratio_width); pixels_left_height = height - (new_height * height_inc); pixels_left_width = width - (new_width * width_inc); int * height_inc_array = new int [new_height + 1]; int * width_inc_array = new int [new_width + 1]; for(i = 0; i < new_height; i++) { height_inc_array[i] = height_inc; if(pixels_left_height > 0) { height_inc_array[i]++; pixels_left_height--; } if(i == new_height - 1 && pixels_left_height > 0) { i = -1; } } height_inc_array[new_height] = 100; for(j = 0; j < new_width; j++) { width_inc_array[j] = width_inc; if(pixels_left_width > 0) { width_inc_array[j]++; pixels_left_width--; } if(j == new_width - 1 && pixels_left_width > 0) { j = -1; } } width_inc_array[new_width] = 100; // On parcourt tout le tableau for(i = 0; i < height; i = i + height_inc_array[cur_new_i - 1]) { cur_new_j = 0; for(j = 0; j < width; j = j + width_inc_array[cur_new_j - 1]) { sum_R = 0.0; sum_G = 0.0; sum_B = 0.0; count = 0; for(i_1 = 0; i_1 <= height_inc_array[cur_new_i]; i_1++) { for(j_1 = 0; j_1 <= width_inc_array[cur_new_j]; j_1++) { if(i + i_1 >= 0 && i + i_1 < height && j + j_1 >= 0 && j + j_1 < width) { sum_R += array[i + i_1][j + j_1].R; sum_G += array[i + i_1][j + j_1].G; sum_B += array[i + i_1][j + j_1].B; count++; } } } array_ter[cur_new_i][cur_new_j].R = int(sum_R / count); array_ter[cur_new_i][cur_new_j].G = int(sum_G / count); array_ter[cur_new_i][cur_new_j].B = int(sum_B / count); cur_new_j++; } cur_new_i++; } for(i = 0; i < height; i++) { delete[] array[i]; } delete[] array; width = new_width; height = new_height; return array_ter;}