#include "config.h" #include #include #include #include #include #include #include "main.h" #include "render.h" #include "texturize.h" #include "plugin-intl.h" // Computes the distance between image_tab and patch_tab for the zone that's // been filled in: // (x_min,y_min) -> (x_max,y_max) in image_tab // (x_min,y_min)-posn -> (x_max,y_max) - posn in patch_tab float difference (gint width_i, gint height_i, gint width_p, gint height_p, guchar * image, guchar * patch, gint posn_x, gint posn_y, gint x_min, gint y_min, gint x_max, gint y_max, gint channels, guchar ** filled) { gint somme = 0, zone=0; gint x_i, y_i, k; guchar *image_ptr, *patch_ptr; // slow // gint real_y_i, real_x_i; // for (y_i = y_min; y_i < y_max; y_i++) { // real_y_i = modulo (y_i, height_i); // for (x_i = x_min; x_i < x_max; x_i++) { // real_x_i = modulo (x_i, width_i); // if (filled[real_x_i][real_y_i]) { // image_ptr = image + (real_y_i * width_i + real_x_i) * channels; // patch_ptr = patch + (modulo(real_y_i - posn_y, height_p) * width_p // + modulo(real_x_i - posn_x, width_p)) * channels; // for (k = 0 ; k < channels; k++) { // somme += abs (*image_ptr++ - *patch_ptr++); // zone ++; // } // } // } // } // fast gint x_p, y_p; gint x_i_start, x_p_start; gint xcount, ycount; gint iy, ix; guchar *image_ptr_x, *patch_ptr_x; gint image_add_y, patch_add_y; ycount = y_max - y_min; xcount = x_max - x_min; y_i = modulo(y_min, height_i); y_p = modulo(y_i - posn_y, height_p); image_add_y = width_i * channels; patch_add_y = width_p * channels; image_ptr_x = image + y_i * image_add_y; patch_ptr_x = patch + y_p * patch_add_y; x_i_start = modulo(x_min, width_i); x_p_start = modulo(x_i_start - posn_x, width_p); for(iy = 0; iy < ycount; iy++) { x_i = x_i_start; x_p = x_p_start; image_ptr = image_ptr_x + x_i * channels; patch_ptr = patch_ptr_x + x_p * channels; for (ix = 0; ix < xcount; ix++) { if (filled[x_i][y_i]) { for (k = 0 ; k < channels; k++) { somme += abs (*image_ptr - *patch_ptr); image_ptr++; patch_ptr++; zone++; } } else { image_ptr += channels; patch_ptr += channels; } if (++x_i >= width_i) { x_i = 0; image_ptr = image_ptr_x; } if (++x_p >= width_p) { x_p = 0; patch_ptr = patch_ptr_x; } } image_ptr_x += image_add_y; patch_ptr_x += patch_add_y; if (++y_i >= height_i) { y_i = 0; image_ptr_x = image; } if (++y_p >= height_p) { y_p = 0; patch_ptr_x = patch; } } if (zone == 0) {printf("Bug: Zone = 0\n"); exit(-1);} return (((float) somme) / ((float) zone)); } void offset_optimal (gint *resultat, guchar *image, guchar *patch, gint width_p, gint height_p, gint width_i, gint height_i, gint x_patch_posn_min, gint y_patch_posn_min, gint x_patch_posn_max, gint y_patch_posn_max, gint channels, guchar **filled, gboolean tileable) { gint x_i, y_i; float best_difference = INFINITY, tmp_difference; if (tileable) { for (x_i = x_patch_posn_min; x_i < x_patch_posn_max; x_i++) { for (y_i = y_patch_posn_min; y_i < y_patch_posn_max; y_i++) { tmp_difference = difference ( width_i, height_i, width_p, height_p, image, patch, x_i, y_i, MAX (0, x_i), MAX (0, y_i), x_i + width_p, y_i + height_p, channels, filled); if (tmp_difference < best_difference) { best_difference = tmp_difference; resultat[0] = x_i; resultat[1] = y_i; } } } } else { for (x_i = x_patch_posn_min; x_i < x_patch_posn_max; x_i++) { for (y_i = y_patch_posn_min; y_i < y_patch_posn_max; y_i++) { tmp_difference = difference ( width_i, height_i, width_p, height_p, image, patch, x_i, y_i, MAX (0, x_i), MAX (0, y_i), MIN (x_i + width_p, width_i), MIN (y_i + height_p, height_i), channels, filled); if (tmp_difference < best_difference) { best_difference = tmp_difference; resultat[0] = x_i; resultat[1] = y_i; } } } } return; }