[gegl] global-matting: resynced with rggjan's repo



commit 376e3fef0cd33039f710508f67bded202f542583
Author: Jan RÃegg <rggjan gmail com>
Date:   Mon Mar 26 21:38:43 2012 +0200

    global-matting: resynced with rggjan's repo
    
    ! Changed matting reference image
    ! Fixed Copyright
    + Added levels to gegl chant for matting
    + Better adaption to gimp HACKORDNUNG
    c Adapted user message
    c Cleanup
    - Removed unused function
    ! Fixed nasty memory bug

 operations/common/matting-global.c              |  542 ++++++++++-------------
 tests/compositions/matting-global.xml           |    7 +-
 tests/compositions/reference/matting-global.png |  Bin 52292 -> 1241155 bytes
 3 files changed, 236 insertions(+), 313 deletions(-)
---
diff --git a/operations/common/matting-global.c b/operations/common/matting-global.c
index 94ec815..802ce0a 100644
--- a/operations/common/matting-global.c
+++ b/operations/common/matting-global.c
@@ -13,66 +13,51 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
  *
- * Copyright 2010 Danny Robson <danny blubinc net>
- * Based off 2006 Anat Levin
+ * Copyright 2011 Jan RÃegg <rggjan gmail com>
  */
 
 #include "config.h"
 #include <glib/gi18n-lib.h>
+#include <math.h>
 
 #ifdef GEGL_CHANT_PROPERTIES
 
-gegl_chant_int    (epsilon, _("Epsilon"),
-                   -9, -1, -6,
-                   _("Log of the error weighting"))
-gegl_chant_int    (radius, _("Radius"),
-                   1, 3, 1,
-                   _("Radius of the processing window"))
-gegl_chant_double (threshold, _("Threshold"),
-                   0.0, 0.1, 0.02,
-                   _("Alpha threshold for multilevel processing"))
-gegl_chant_double (lambda, _("Lambda"),
-                   0.0, 100.0, 100.0, _("Trimap influence factor"))
-gegl_chant_int    (levels, _("Levels"),
-                   0, 8, 4,
-                   _("Number of downsampled levels to use"))
-gegl_chant_int    (active_levels, _("Active Levels"),
-                   0, 8, 2,
-                   _("Number of levels to perform solving"))
+gegl_chant_int (iterations, _("Iterations"), 1, G_MAXINT, 10,
+                _("Number of iterations"))
+
 #else
 
 #define GEGL_CHANT_TYPE_COMPOSER
-#define GEGL_CHANT_C_FILE       "matting-global.c"
+#define GEGL_CHANT_C_FILE "matting-global.c"
 
 #include "gegl-chant.h"
 #include "gegl-debug.h"
-#include <stdlib.h>
-
-#include <stdio.h>
-#include <math.h>
 
 #define max(a,b) \
-   ({ __typeof__ (a) _a = (a); \
-       __typeof__ (b) _b = (b); \
-     _a > _b ? _a : _b; })
+  ({ __typeof__ (a) _a = (a); \
+  __typeof__ (b) _b = (b); \
+  _a > _b ? _a : _b; })
 
 #define min(a,b) \
-   ({ __typeof__ (a) _a = (a); \
-       __typeof__ (b) _b = (b); \
-     _a > _b ? _b : _a; })
-
+  ({ __typeof__ (a) _a = (a); \
+  __typeof__ (b) _b = (b); \
+  _a > _b ? _b : _a; })
 
 #define likely(x)       __builtin_expect((x),1)
 #define unlikely(x)       __builtin_expect((x),0)
 
 #define ASSERT(condition) \
-   if(unlikely(!(condition))) { \
-     printf("Error at line %i\n", __LINE__); \
-     exit(1);\
-   }
+  if(unlikely(!(condition))) { \
+  printf("Error at line %i\n", __LINE__); \
+  exit(1);\
+  }
 
+// Shortcut for doing things in all three channels
 #define COLOR(expr) {int c; for (c = 0; c < 3; c++) { expr; }}
 
+// Save all important memories to output image buffer to save memory
+#define FG_DISTANCE(output, index) (output[index*4+0])
+#define BG_DISTANCE(output, index) (output[index*4+1])
 #define FG_INDEX(output, index) (*((int*)(&output[index*4+2])))
 #define BG_INDEX(output, index) (*((int*)(&output[index*4+3])))
 
@@ -89,7 +74,8 @@ static const gchar *FORMAT_INPUT  = "R'G'B' float";
 static const gchar *FORMAT_OUTPUT = "R'G'B'A float";
 
 static void
-matting_prepare (GeglOperation *operation) {
+matting_prepare (GeglOperation *operation)
+{
   gegl_operation_set_format (operation, "input",  babl_format (FORMAT_INPUT));
   gegl_operation_set_format (operation, "aux",    babl_format (FORMAT_AUX));
   gegl_operation_set_format (operation, "output", babl_format (FORMAT_OUTPUT));
@@ -98,7 +84,8 @@ matting_prepare (GeglOperation *operation) {
 static GeglRectangle
 matting_get_required_for_output (GeglOperation       *operation,
                                  const gchar         *input_pad,
-                                 const GeglRectangle *roi) {
+                                 const GeglRectangle *roi)
+{
   GeglRectangle result = *gegl_operation_source_get_bounding_box (operation,
                                                                   "input");
   return result;
@@ -106,7 +93,8 @@ matting_get_required_for_output (GeglOperation       *operation,
 
 static GeglRectangle
 matting_get_cached_region (GeglOperation * operation,
-                           const GeglRectangle * roi) {
+                           const GeglRectangle * roi)
+{
   return *gegl_operation_source_get_bounding_box (operation, "input");
 }
 
@@ -123,40 +111,47 @@ typedef struct {
 } ColorSample;
 
 #define SQUARE(x) ((x)*(x))
-static inline float get_alpha (Color F, Color B, Color I) {
+static inline float get_alpha (Color F, Color B, Color I)
+{
   int c;
   float result = 0;
   float div = 0;
-  for (c = 0; c < 3; c++) {
-    result += (I[c] - B[c]) * (F[c] - B[c]);
-    div += SQUARE(F[c] - B[c]);
-  }
+  for (c = 0; c < 3; c++)
+    {
+      result += (I[c] - B[c]) * (F[c] - B[c]);
+      div += SQUARE(F[c] - B[c]);
+    }
   return min(max(result / div, 0), 1);
 }
 
-static inline float get_color_cost (Color F, Color B, Color I, float alpha) {
+static inline float get_color_cost (Color F, Color B, Color I, float alpha)
+{
   int c;
   float result = 0;
-  for (c = 0; c < 3; c++) {
-    result += SQUARE(I[c] - (alpha * F[c] + (1 - alpha) * B[c]));
-  }
+  for (c = 0; c < 3; c++)
+    {
+      result += SQUARE(I[c] - (alpha * F[c] + (1 - alpha) * B[c]));
+    }
 
   // TODO(rggjan): Remove sqrt to get faster code?
   // TODO(rggjan): Remove 255
   return sqrt(result) * 255;
 }
 
-static inline int get_distance_squared(ColorSample s, int x, int y) {
+static inline int get_distance_squared(ColorSample s, int x, int y)
+{
   return SQUARE(s.pos.x - x) + SQUARE(s.pos.y - y);
 }
 
-static inline float get_distance (ColorSample s, int x, int y) {
+static inline float get_distance (ColorSample s, int x, int y)
+{
   // TODO(rggjan): Remove sqrt to get faster code?
   return sqrt(get_distance_squared(s, x, y));
 }
 
 
-static inline float get_distance_cost (ColorSample s, int x, int y, float *best_distance) {
+static inline float get_distance_cost (ColorSample s, int x, int y, float *best_distance)
+{
   float new_distance = get_distance(s, x, y);
 
   if (new_distance < *best_distance)
@@ -165,148 +160,61 @@ static inline float get_distance_cost (ColorSample s, int x, int y, float *best_
   return new_distance / *best_distance;
 }
 
-static inline float get_cost (ColorSample foreground, ColorSample background, Color I, int x, int y, float *best_fg_distance, float *best_bg_distance, Color avgf, Color avgb, float devf, float devb) {
-  float cost = 0;
-  //printf("I: %f/%f/%f at %i,%i\n", I[0], I[1], I[2], x, y);
-  //printf("best: %f/%f\n", best_fg_distance, best_bg_distance);
-  //printf("F: %f/%f/%f at %i,%i\n", foreground.color[0], foreground.color[1], foreground.color[2], foreground.pos[0], foreground.pos[1]);
-  //printf("B: %f/%f/%f at %i,%i\n", background.color[0], background.color[1], background.color[2], background.pos[0], background.pos[1]);
-
-//  COLOR(cost += SQUARE(foreground.color[c] - avgf[c]) / devf);
-//  COLOR(cost += SQUARE(background.color[c] - avgb[c]) / devb);
-  //cost *= 255;
-
-  cost += get_color_cost(foreground.color, background.color, I,
-                         get_alpha(foreground.color, background.color, I));
-  //printf("cost1: %f\n", cost);
+static inline float get_cost (ColorSample foreground, ColorSample background, Color I, int x, int y, float *best_fg_distance, float *best_bg_distance)
+{
+  float cost = get_color_cost(foreground.color, background.color, I,
+                              get_alpha(foreground.color, background.color, I));
   cost += get_distance_cost(foreground, x, y, best_fg_distance);
-  //printf("costf: %f\n", get_distance_cost(foreground, x, y, best_fg_distance));
   cost += get_distance_cost(background, x, y, best_bg_distance);
-  //printf("costb: %f\n", get_distance_cost(foreground, x, y, best_bg_distance));
   return cost;
 }
 
-static inline void get_average (GArray *foreground_samples, GArray *background_samples, gfloat *input, gfloat *output, int x, int y, int w, int h, float *avgf, float *avgb, float *devf, float *devb) {
-  int xdiff, ydiff;
-  int fg_count = 0;
-  int bg_count = 0;
-
-/*  COLOR(avgf[c] = 0);
-  COLOR(avgb[c] = 0);
-  *devf = 0;
-  *devb = 0;*/
-
-  // Get average
-  for (ydiff = -1; ydiff <= 1; ydiff++) {
-    // Borders
-    if (y+ydiff < 0 || y+ydiff >= h)
-      continue;
-    for (xdiff = -1; xdiff <= 1; xdiff++) {
-      int i = (y + ydiff) * w + x + xdiff;
-      // Borders
-      if (x+xdiff < 0 || x+xdiff >= w)
-        continue;
-
-      // Distance to background != 0
-      if (output[i * 4 + 1] != 0) {
-        ColorSample foreground = g_array_index(foreground_samples, ColorSample, FG_INDEX(output, i));
-        COLOR(avgf[c] += foreground.color[c]);
-        fg_count++;
-      }
-
-      // Distance to foreground != 0
-      if (output[i * 4 + 0] != 0) {
-        ColorSample background = g_array_index(background_samples, ColorSample, BG_INDEX(output, i));
-        COLOR(avgb[c] += background.color[c]);
-        bg_count++;
-      }
-    }
-  }
-
-  ASSERT(fg_count > 0);
-  ASSERT(bg_count > 0);
-
-  COLOR(avgf[c] /= fg_count);
-  COLOR(avgb[c] /= bg_count);
-
-//  COLOR(printf("%f ", avgf[c]));
-//  printf("\n\n");
-
-  // get deviation
-  for (ydiff = -1; ydiff <= 1; ydiff++) {
-    // Borders
-    if (y+ydiff < 0 || y+ydiff >= h)
-      continue;
-    for (xdiff = -1; xdiff <= 1; xdiff++) {
-      int i = (y + ydiff) * w + x + xdiff;
-      // Borders
-      if (x+xdiff < 0 || x+xdiff >= w)
-        continue;
-
-      // Distance to background != 0
-      if (output[i * 4 + 1] != 0) {
-        ColorSample foreground = g_array_index(foreground_samples, ColorSample, FG_INDEX(output, i));
-        COLOR(*devf += SQUARE(avgf[c] - foreground.color[c]) / fg_count);
-      }
-
-      // Distance to foreground != 0
-      if (output[i * 4 + 0] != 0) {
-        ColorSample background = g_array_index(background_samples, ColorSample, BG_INDEX(output, i));
-        COLOR(*devb += SQUARE(avgb[c] - background.color[c]) / bg_count);
-      }
-    }
-  }
-}
-
 static inline void do_propagate(GArray *foreground_samples, GArray *background_samples, gfloat *input, gfloat *output, guchar *trimap, int x, int y, int w, int h) {
   int index_orig = y * w + x;
   int index_new;
 
-  Color avgf = {0, 0, 0};
-  Color avgb = {0, 0, 0};
-
-  float devf = 0;
-  float devb = 0;
-
-  get_average(foreground_samples, background_samples, input, output, x, y, w, h, avgf, avgb, &devf, &devb);
-
-  if (!(trimap[index_orig] == 0 || trimap[index_orig] == 255)) {
-    int xdiff, ydiff;
-    float best_cost = FLT_MAX;
-    float *best_fg_distance = &output[index_orig * 4 + 0];
-    float *best_bg_distance = &output[index_orig * 4 + 1];
-
-    for (ydiff = -1; ydiff <= 1; ydiff++) {
-      // Borders
-      if (y+ydiff < 0 || y+ydiff >= h)
-        continue;
-      for (xdiff = -1; xdiff <= 1; xdiff++) {
-        // Borders
-        if (x+xdiff < 0 || x+xdiff >= w)
-          continue;
-
-        index_new = (y + ydiff) * w + (x + xdiff);
-
-        if (!(trimap[index_new] == 0 || trimap[index_new] == 255)) {
-          int fi = FG_INDEX(output, index_new);
-          int bi = BG_INDEX(output, index_new);
-
-          ColorSample foreground = g_array_index(foreground_samples, ColorSample, fi);
-          ColorSample background = g_array_index(background_samples, ColorSample, bi);
+  if (!(trimap[index_orig] == 0 || trimap[index_orig] == 255))
+    {
+      int xdiff, ydiff;
+      float best_cost = FLT_MAX;
+      float *best_fg_distance = &output[index_orig * 4 + 0];
+      float *best_bg_distance = &output[index_orig * 4 + 1];
 
-          float cost = get_cost(foreground, background, &input[index_orig * 3], x, y, best_fg_distance, best_bg_distance, avgf, avgb, devf, devb);
-          if (cost < best_cost) {
-            FG_INDEX(output, index_orig) = fi;
-            BG_INDEX(output, index_orig) = bi;
-            best_cost = cost;
-          }
+      for (ydiff = -1; ydiff <= 1; ydiff++)
+        {
+          // Borders
+          if (y+ydiff < 0 || y+ydiff >= h)
+            continue;
+          for (xdiff = -1; xdiff <= 1; xdiff++)
+            {
+              // Borders
+              if (x+xdiff < 0 || x+xdiff >= w)
+                continue;
+
+              index_new = (y + ydiff) * w + (x + xdiff);
+
+              if (!(trimap[index_new] == 0 || trimap[index_new] == 255))
+                {
+                  int fi = FG_INDEX(output, index_new);
+                  int bi = BG_INDEX(output, index_new);
+
+                  ColorSample foreground = g_array_index(foreground_samples, ColorSample, fi);
+                  ColorSample background = g_array_index(background_samples, ColorSample, bi);
+
+                  float cost = get_cost(foreground, background, &input[index_orig * 3], x, y, best_fg_distance, best_bg_distance);
+                  if (cost < best_cost)
+                    {
+                      FG_INDEX(output, index_orig) = fi;
+                      BG_INDEX(output, index_orig) = bi;
+                      best_cost = cost;
+                    }
+                }
+            }
         }
-      }
     }
-  }
 }
 
-static inline void do_random_search(GArray *foreground_samples, GArray *background_samples, gfloat *input, gfloat *output, int x, int y, int w, int h) {
+static inline void do_random_search(GArray *foreground_samples, GArray *background_samples, gfloat *input, gfloat *output, int x, int y, int w) {
   int dist_f = foreground_samples->len;
   int dist_b = background_samples->len;
   int index = y * w + x;
@@ -317,53 +225,52 @@ static inline void do_random_search(GArray *foreground_samples, GArray *backgrou
   int start_fi = best_fi;
   int start_bi = best_bi;
 
-  Color avgf = {0, 0, 0};
-  Color avgb = {0, 0, 0};
-
-  float devf = 0;
-  float devb = 0;
-
   // Get current best result
-  float *best_fg_distance = &output[index * 4 + 0];
-  float *best_bg_distance = &output[index * 4 + 1];
+  float *best_fg_distance = &FG_DISTANCE(output, index);
+  float *best_bg_distance = &BG_DISTANCE(output, index);
 
   ColorSample foreground = g_array_index(foreground_samples, ColorSample, best_fi);
   ColorSample background = g_array_index(background_samples, ColorSample, best_bi);
 
-  float best_cost;
-
-  // Get average cost
-  get_average(foreground_samples, background_samples, input, output, x, y, w, h, avgf, avgb, &devf, &devb);
-  best_cost = get_cost(foreground, background, &input[index * 3], x, y, best_fg_distance, best_bg_distance, avgf, avgb, devf, devb);
-
-  //printf("Got best cost: %i\n", best_cost);
-  while (dist_f > 0 && dist_b > 0) {
-    int fi, bi;
-    float cost;
-    ColorSample background, foreground;
-    fi = (start_fi + (rand() % (dist_f * 2 + 1)) - dist_f) % foreground_samples->len;
-    bi = (start_bi + (rand() % (dist_b * 2 + 1)) - dist_b) % background_samples->len;
-    background = g_array_index(background_samples, ColorSample, bi);
-    foreground = g_array_index(foreground_samples, ColorSample, fi);
-    cost = get_cost(foreground, background, &input[index * 3], x, y, best_fg_distance, best_bg_distance, avgf, avgb, devf, devb);
-    if (cost < best_cost) {
-      best_cost = cost;
-      best_fi = fi;
-      best_bi = bi;
+  // Get cost
+  float best_cost = get_cost(foreground, background, &input[index * 3], x, y, best_fg_distance, best_bg_distance);
+
+  while (dist_f > 0 || dist_b > 0)
+    {
+      // Get new indices to check
+      int fl = foreground_samples->len;
+      int bl = background_samples->len;
+      int fi = (start_fi + (rand() % (dist_f * 2 + 1)) + fl - dist_f) % fl;
+      int bi = (start_bi + (rand() % (dist_b * 2 + 1)) + fl - dist_b) % bl;
+
+      ColorSample foreground = g_array_index(foreground_samples, ColorSample, fi);
+      ColorSample background = g_array_index(background_samples, ColorSample, bi);
+
+      float cost = get_cost(foreground, background, &input[index * 3], x, y, best_fg_distance, best_bg_distance);
+
+      if (cost < best_cost)
+        {
+          best_cost = cost;
+          best_fi = fi;
+          best_bi = bi;
+        }
+      dist_f /= 2;
+      dist_b /= 2;
     }
-    dist_f /= 2;
-    dist_b /= 2;
-  }
 
   FG_INDEX(output, index) = best_fi;
   BG_INDEX(output, index) = best_bi;
 }
 
-static gint color_compare(gconstpointer p1, gconstpointer p2) {
+// Compare color intensities
+static gint color_compare(gconstpointer p1, gconstpointer p2)
+{
   ColorSample *s1 = (ColorSample*) p1;
   ColorSample *s2 = (ColorSample*) p2;
+
   float sum1 = s1->color[0] + s1->color[1] + s1->color[2];
   float sum2 = s2->color[0] + s2->color[1] + s2->color[2];
+
   return ((sum1 > sum2) - (sum2 > sum1));
 }
 
@@ -376,7 +283,7 @@ matting_process (GeglOperation       *operation,
                  int                  level)
 {
 
-  //const GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+  const GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
   gfloat           *input   = NULL;
   guchar           *trimap  = NULL;
   gfloat           *output  = NULL;
@@ -412,130 +319,151 @@ matting_process (GeglOperation       *operation,
   unknown_positions = g_array_new(FALSE, FALSE, sizeof(Position));
 
   // Get mask
-  for (y = 0; y < h; y++) {
-    for (x = 0; x < w; x++) {
-      int mask = trimap[y * w + x];
-      for (ydiff = -1; ydiff <= 1; ydiff++) {
-        // Borders
-        if (y+ydiff < 0 || y+ydiff >= h)
-          continue;
-
-        for (xdiff = -1; xdiff <= 1; xdiff++) {
-          // Borders
-          if (x+xdiff < 0 || x+xdiff >= w)
-            continue;
-
-          neighbour_mask = trimap[(y + ydiff) * w + x + xdiff];
-          if (neighbour_mask != mask && (mask == 0 || mask == 255)) {
-            int index = y*w+x;
-            ColorSample s;
-            s.pos.x = x;
-            s.pos.y = y;
-            COLOR(s.color[c] = input[index * 3 + c])
-
-            if (mask == 255) {
-              g_array_append_val(foreground_samples, s);
-              output[index*4+0] = 0;
-              output[index*4+1] = FLT_MAX;
-            } else {
-              g_array_append_val(background_samples, s);
-              output[index*4+0] = FLT_MAX;
-              output[index*4+1] = 0;
+  for (y = 0; y < h; y++)
+    {
+      for (x = 0; x < w; x++)
+        {
+          int mask = trimap[y * w + x];
+          for (ydiff = -1; ydiff <= 1; ydiff++)
+            {
+              // Borders
+              if (y+ydiff < 0 || y+ydiff >= h)
+                continue;
+
+              for (xdiff = -1; xdiff <= 1; xdiff++)
+                {
+                  // Borders
+                  if (x+xdiff < 0 || x+xdiff >= w)
+                    continue;
+
+                  neighbour_mask = trimap[(y + ydiff) * w + x + xdiff];
+                  if (neighbour_mask != mask && (mask == 0 || mask == 255))
+                    {
+                      int index = y*w+x;
+                      ColorSample s;
+                      s.pos.x = x;
+                      s.pos.y = y;
+                      COLOR(s.color[c] = input[index*3 + c]);
+
+                      if (mask == 255)
+                        {
+                          g_array_append_val(foreground_samples, s);
+                          FG_DISTANCE(output, index) = 0;
+                          BG_DISTANCE(output, index) = FLT_MAX;
+                        }
+                      else
+                        {
+                          g_array_append_val(background_samples, s);
+                          FG_DISTANCE(output, index) = 0;
+                          BG_DISTANCE(output, index) = FLT_MAX;
+                        }
+
+                      // Go to next pixel
+                      xdiff = 1;
+                      ydiff = 1;
+                    }
+                }
             }
-
-            // Go to next pixel
-            xdiff = 1;
-            ydiff = 1;
-          }
         }
-      }
     }
-  }
 
-  // Initialize
-  for (y = 0; y < h; y++) {
-    for (x = 0; x < w; x++) {
-      int index = y * w + x;
-
-      if (trimap[index] != 0 && trimap[index] != 255) {
-        Position p;
-        p.x = x;
-        p.y = y;
-        g_array_append_val(unknown_positions, p);
-        output[index * 4 + 0] = FLT_MAX;
-        output[index * 4 + 1] = FLT_MAX;
-        FG_INDEX(output, index) = rand() % foreground_samples->len;
-        BG_INDEX(output, index) = rand() % background_samples->len;
-      }
+  // Initialize unknowns
+  for (y = 0; y < h; y++)
+    {
+      for (x = 0; x < w; x++)
+        {
+          int index = y * w + x;
+
+          if (trimap[index] != 0 && trimap[index] != 255)
+            {
+              Position p;
+              p.x = x;
+              p.y = y;
+              g_array_append_val(unknown_positions, p);
+              FG_DISTANCE(output, index) = FLT_MAX;
+              BG_DISTANCE(output, index) = FLT_MAX;
+              FG_INDEX(output, index) = rand() % foreground_samples->len;
+              BG_INDEX(output, index) = rand() % background_samples->len;
+            }
+        }
     }
-  }
 
   g_array_sort(foreground_samples, color_compare);
   g_array_sort(background_samples, color_compare);
 
-  for (i = 0; i < 10; i++) {
-    int j;
+  // Do real iterations
+  for (i = 0; i < o->iterations; i++)
+    {
+      unsigned j;
 
-    printf("Iteration %i\n", i);
+      GEGL_NOTE (GEGL_DEBUG_PROCESS, "Iteration %i", i);
 
-    for (j=0; j<unknown_positions->len; j++) {
-      Position p = g_array_index(unknown_positions, Position, j);
-      int x = p.x;
-      int y = p.y;
-      do_random_search(foreground_samples, background_samples, input, output, x, y, w, h);
-    }
+      for (j=0; j<unknown_positions->len; j++)
+        {
+          Position p = g_array_index(unknown_positions, Position, j);
+          do_random_search(foreground_samples, background_samples, input, output, p.x, p.y, w);
+        }
 
-    for (j=0; j<unknown_positions->len; j++) {
-      Position p = g_array_index(unknown_positions, Position, j);
-      int x = p.x;
-      int y = p.y;
-      do_propagate(foreground_samples, background_samples, input, output, trimap, x, y, w, h);
+      for (j=0; j<unknown_positions->len; j++)
+        {
+          Position p = g_array_index(unknown_positions, Position, j);
+          do_propagate(foreground_samples, background_samples, input, output, trimap, p.x, p.y, w, h);
+        }
     }
-      
-  }
 
-  for (y = 0; y < h; y++) {
-    for (x = 0; x < w; x++) {
-      int index = y * w + x;
-      if (trimap[index] == 0 || trimap[index] == 255) {
-        // Use known values
-        output[index * 4 + 0] = input[index * 3 + 0];
-        output[index * 4 + 1] = input[index * 3 + 1];
-        output[index * 4 + 2] = input[index * 3 + 2];
-
-        if (trimap[index] == 0) {
-          output[index * 4 + 3] = 0;
-        } else if (trimap[index] == 255) {
-          output[index * 4 + 3] = 1;
-        }
-      } else {
-        int c;
-        ColorSample background, foreground;
-        foreground = g_array_index(foreground_samples, ColorSample, FG_INDEX(output, index));
-        background = g_array_index(background_samples, ColorSample, BG_INDEX(output, index));
+  // Fill results in
+  for (y = 0; y < h; y++)
+    {
+      for (x = 0; x < w; x++)
+        {
+          int index = y * w + x;
+          if (trimap[index] == 0 || trimap[index] == 255)
+            {
+              // Use known values
+              output[index * 4 + 0] = input[index * 3 + 0];
+              output[index * 4 + 1] = input[index * 3 + 1];
+              output[index * 4 + 2] = input[index * 3 + 2];
+
+              if (trimap[index] == 0)
+                {
+                  output[index * 4 + 3] = 0;
+                }
+              else if (trimap[index] == 255)
+                {
+                  output[index * 4 + 3] = 1;
+                }
+            }
+          else
+            {
+              ColorSample background, foreground;
+              foreground = g_array_index(foreground_samples, ColorSample, FG_INDEX(output, index));
+              background = g_array_index(background_samples, ColorSample, BG_INDEX(output, index));
 
-        output[index * 4 + 3] = get_alpha(foreground.color, background.color, &input[index * 3]);
+              output[index * 4 + 3] = get_alpha(foreground.color, background.color, &input[index * 3]);
 
-        for (c = 0; c < 3; c++) {
-          output[index * 4 + c] = foreground.color[c];
+              COLOR(output[index * 4 + c] = foreground.color[c]);
+            }
         }
-      }
     }
-  }
 
+  // Save to buffer
   gegl_buffer_set (output_buf, result, 0, babl_format (FORMAT_OUTPUT), output,
                    GEGL_AUTO_ROWSTRIDE);
   success = TRUE;
+
+  // Free memory
   g_free (input);
   g_free (trimap);
   g_free (output);
   g_array_free(foreground_samples, FALSE);
   g_array_free(background_samples, FALSE);
   g_array_free(unknown_positions, FALSE);
+
   return success;
 }
 
-static void gegl_chant_class_init (GeglChantClass *klass) {
+static void gegl_chant_class_init (GeglChantClass *klass)
+{
   GeglOperationClass         *operation_class;
   GeglOperationComposerClass *composer_class;
 
@@ -551,9 +479,9 @@ static void gegl_chant_class_init (GeglChantClass *klass) {
     "name"       , "gegl:matting-global",
     "categories" , "misc",
     "description",
-      _("Given a sparse user supplied tri-map and an input image, create a "
-        "foreground alpha mat. Set white as selected, black as unselected, "
-        "for the tri-map."),
+   _("Given a sparse user supplied tri-map and an input image, create a "
+     "foreground alpha matte. Set white as foreground, black as background "
+     "for the tri-map. Everything else will be treated as unknown and filled in."),
     NULL);
 }
 #endif
diff --git a/tests/compositions/matting-global.xml b/tests/compositions/matting-global.xml
index 88ed5db..77c8205 100644
--- a/tests/compositions/matting-global.xml
+++ b/tests/compositions/matting-global.xml
@@ -1,11 +1,6 @@
 <?xml version='1.0' encoding='UTF-8'?>
 <gegl>
-  <node operation='gegl:matting-global'>
-    <params>
-      <param name='levels'>1</param>
-      <param name='active_levels'>1</param>
-    </params>
-
+  <node operation='gegl:matting-global' iterations='10'>
     <node operation='gegl:load'>
       <params>
         <param name='path'>data/matting-global_scribble.png</param>
diff --git a/tests/compositions/reference/matting-global.png b/tests/compositions/reference/matting-global.png
index f367c08..7beac95 100644
Binary files a/tests/compositions/reference/matting-global.png and b/tests/compositions/reference/matting-global.png differ



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]