[gegl] operations: deep cleanup of image-compare



commit ea168f85c155d4444d64d8b491cedae93636e9b1
Author: Téo Mazars <teo mazars ensimag fr>
Date:   Tue Oct 15 14:52:43 2013 +0200

    operations: deep cleanup of image-compare
    
    - use iterators instead of allocating the whole input
    - iterate only once
    - implement get_cached_region to avoid any chunking
    - use CIELab alpha instead of CIELab + RGBA
    - try to stay in 80 columns and other format fixes
    - add myself to the authors list

 operations/common/image-compare.c |  211 ++++++++++++++++---------------------
 1 files changed, 89 insertions(+), 122 deletions(-)
---
diff --git a/operations/common/image-compare.c b/operations/common/image-compare.c
index 26bf56b..88217c8 100644
--- a/operations/common/image-compare.c
+++ b/operations/common/image-compare.c
@@ -15,6 +15,7 @@
  *
  * Copyright 2010 Øyvind Kolås <pippin gimp org>
  *           2012 Ville Sokk <ville sokk gmail com>
+ *           2013 Téo Mazars <teo mazars ensimag fr>
  */
 
 #include "config.h"
@@ -23,10 +24,21 @@
 
 #ifdef GEGL_CHANT_PROPERTIES
 
-gegl_chant_int (wrong_pixels, _("Wrong pixels"), G_MININT, G_MAXINT, 0, _("Number of differing pixels."))
-gegl_chant_double (max_diff, _("Maximum difference"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, _("Maximum difference 
between two pixels."))
-gegl_chant_double (avg_diff_wrong, _("Average difference (wrong)"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, 
_("Average difference between wrong pixels."))
-gegl_chant_double (avg_diff_total, _("Average difference (total)"), -G_MAXDOUBLE, G_MAXDOUBLE, 0.0, 
_("Average difference between all pixels."))
+gegl_chant_int    (wrong_pixels, _("Wrong pixels"),
+                   G_MININT, G_MAXINT, 0,
+                   _("Number of differing pixels."))
+
+gegl_chant_double (max_diff, _("Maximum difference"),
+                   -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+                   _("Maximum difference between two pixels."))
+
+gegl_chant_double (avg_diff_wrong, _("Average difference (wrong)"),
+                   -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+                   _("Average difference between wrong pixels."))
+
+gegl_chant_double (avg_diff_total, _("Average difference (total)"),
+                   -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+                   _("Average difference between all pixels."))
 
 #else
 
@@ -35,12 +47,14 @@ gegl_chant_double (avg_diff_total, _("Average difference (total)"), -G_MAXDOUBLE
 
 #include "gegl-chant.h"
 
+#define ERROR_TOLERANCE 0.01
+#define SQR(x)          ((x) * (x))
 
 static void
 prepare (GeglOperation *self)
 {
-  gegl_operation_set_format (self, "input", babl_format ("CIE Lab float"));
-  gegl_operation_set_format (self, "aux", babl_format ("CIE Lab float"));
+  gegl_operation_set_format (self, "input",  babl_format ("CIE Lab alpha float"));
+  gegl_operation_set_format (self, "aux",    babl_format ("CIE Lab alpha float"));
   gegl_operation_set_format (self, "output", babl_format ("R'G'B' u8"));
 }
 
@@ -49,12 +63,15 @@ get_required_for_output (GeglOperation       *operation,
                          const gchar         *input_pad,
                          const GeglRectangle *region)
 {
-  GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
-
-  return result;
+  return *gegl_operation_source_get_bounding_box (operation, "input");
 }
 
-#define SQR(x) ((x) * (x))
+static GeglRectangle
+get_cached_region (GeglOperation       *operation,
+                   const GeglRectangle *roi)
+{
+  return *gegl_operation_source_get_bounding_box (operation, "input");
+}
 
 static gboolean
 process (GeglOperation       *operation,
@@ -64,129 +81,78 @@ process (GeglOperation       *operation,
          const GeglRectangle *result,
          gint                 level)
 {
-  GeglChantO  *props        = GEGL_CHANT_PROPERTIES (operation);
-  gdouble      max_diff     = 0.0;
-  gdouble      diffsum      = 0.0;
-  gint         wrong_pixels = 0;
-  const Babl*  cielab       = babl_format ("CIE Lab float");
-  const Babl*  rgbaf        = babl_format ("RGBA float");
-  const Babl*  srgb         = babl_format ("R'G'B' u8");
-  gint         pixels, i;
-  gfloat      *in_buf, *aux_buf, *a, *b;
-  gfloat      *in_buf_rgba, *aux_buf_rgba, *aalpha, *balpha;
-  guchar      *out_buf, *out;
+  GeglChantO         *props        = GEGL_CHANT_PROPERTIES (operation);
+  gdouble             max_diff     = 0.0;
+  gdouble             diffsum      = 0.0;
+  gint                wrong_pixels = 0;
+  const Babl         *cielab       = babl_format ("CIE Lab alpha float");
+  const Babl         *srgb         = babl_format ("R'G'B' u8");
+  GeglBufferIterator *gi;
+  gint                index_iter, index_iter2;
 
   if (aux == NULL)
     return TRUE;
 
-  in_buf = g_malloc (result->height * result->width * babl_format_get_bytes_per_pixel (cielab));
-  aux_buf = g_malloc (result->height * result->width * babl_format_get_bytes_per_pixel (cielab));
-
-  in_buf_rgba = g_malloc (result->height * result->width * babl_format_get_bytes_per_pixel (rgbaf));
-  aux_buf_rgba = g_malloc (result->height * result->width * babl_format_get_bytes_per_pixel (rgbaf));
+  gi = gegl_buffer_iterator_new (output, result, 0, srgb,
+                                 GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE);
 
-  out_buf = g_malloc (result->height * result->width * babl_format_get_bytes_per_pixel (srgb));
+  index_iter = gegl_buffer_iterator_add (gi, input, result, 0, cielab,
+                                         GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
 
-  gegl_buffer_get (input, result, 1.0, cielab, in_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-  gegl_buffer_get (aux, result, 1.0, cielab, aux_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+  index_iter2 = gegl_buffer_iterator_add (gi, aux, result, 0, cielab,
+                                         GEGL_BUFFER_READ, GEGL_ABYSS_NONE);
 
-  gegl_buffer_get (input, result, 1.0, rgbaf, in_buf_rgba, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-  gegl_buffer_get (aux, result, 1.0, rgbaf, aux_buf_rgba, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-  a   = in_buf;
-  b   = aux_buf;
-  out = out_buf;
-
-  aalpha = in_buf_rgba;
-  balpha = aux_buf_rgba;
-
-  pixels = result->width * result->height;
-
-  for (i = 0; i < pixels; i++)
+  while (gegl_buffer_iterator_next (gi))
     {
-      gdouble diff = sqrt (SQR(a[0] - b[0])+
-                           SQR(a[1] - b[1])+
-                           SQR(a[2] - b[2]));
+      guint   k;
+      guchar *data_out;
+      gfloat *data_in1;
+      gfloat *data_in2;
 
-      gdouble alpha_diff = abs(aalpha[3] - balpha[3]) * 100.0;
+      data_out = (guchar*) gi->data[0];
+      data_in1 = (gfloat*) gi->data[index_iter];
+      data_in2 = (gfloat*) gi->data[index_iter2];
 
-      if (alpha_diff > diff)
-        diff = alpha_diff;
-
-      if (diff >= 0.01)
-        {
-          wrong_pixels++;
-          diffsum += diff;
-          if (diff > max_diff)
-            max_diff = diff;
-          out[0] = (diff / 100.0 * 255);
-          out[1] = 0;
-          out[2] = a[0] / 100.0 * 255;
-        }
-      else
+      for (k = 0; k < gi->length; k++)
         {
-          out[0] = a[0] / 100.0 * 255;
-          out[1] = a[0] / 100.0 * 255;
-          out[2] = a[0] / 100.0 * 255;
+          gdouble diff = sqrt (SQR (data_in1[0] - data_in2[0]) +
+                               SQR (data_in1[1] - data_in2[1]) +
+                               SQR (data_in1[2] - data_in2[2]));
+
+          gdouble alpha_diff = abs (data_in1[3] - data_in2[3]) * 100.0;
+
+          diff = MAX (diff, alpha_diff);
+
+          if (diff >= ERROR_TOLERANCE)
+            {
+              wrong_pixels++;
+              diffsum += diff;
+
+              if (diff > max_diff)
+                max_diff = diff;
+
+              data_out[0] = CLAMP ((100 - data_in1[0]) / 100.0 * 64 + 32,
+                                   0, 255);
+              data_out[1] = CLAMP (diff / max_diff * 255, 0, 255);
+              data_out[2] = 0;
+            }
+          else
+            {
+              data_out[0] = CLAMP (data_in1[0] / 100.0 * 255, 0, 255);
+              data_out[1] = CLAMP (data_in1[0] / 100.0 * 255, 0, 255);
+              data_out[2] = CLAMP (data_in1[0] / 100.0 * 255, 0, 255);
+            }
+
+          data_out += 3;
+          data_in1 += 4;
+          data_in2 += 4;
         }
-      a   += 3;
-      aalpha += 4;
-      b   += 3;
-      balpha += 4;
-      out += 3;
     }
 
-  a   = in_buf;
-  b   = aux_buf;
-  out = out_buf;
-
-  aalpha = in_buf_rgba;
-  balpha = aux_buf_rgba;
-
-  if (wrong_pixels)
-    for (i = 0; i < pixels; i++)
-      {
-        gdouble diff = sqrt (SQR(a[0] - b[0])+
-                             SQR(a[1] - b[1])+
-                             SQR(a[2] - b[2]));
-
-        gdouble alpha_diff = abs(aalpha[3] - balpha[3]) * 100.0;
-
-        if (alpha_diff > diff)
-          diff = alpha_diff;
-
-        if (diff >= 0.01)
-          {
-            out[0] = (100 - a[0]) / 100.0 * 64 + 32;
-            out[1] = (diff / max_diff * 255);
-            out[2] = 0;
-          }
-        else
-          {
-            out[0] = a[0] / 100.0 * 255;
-            out[1] = a[0] / 100.0 * 255;
-            out[2] = a[0] / 100.0 * 255;
-          }
-        a   += 3;
-        aalpha += 4;
-        b   += 3;
-        balpha += 4;
-        out += 3;
-      }
-
-  gegl_buffer_set (output, result, 1.0, srgb, out_buf, GEGL_AUTO_ROWSTRIDE);
-
-  g_free (in_buf);
-  g_free (aux_buf);
-  g_free (out_buf);
-
-  g_free (in_buf_rgba);
-  g_free (aux_buf_rgba);
-
   props->wrong_pixels   = wrong_pixels;
   props->max_diff       = max_diff;
   props->avg_diff_wrong = diffsum / wrong_pixels;
-  props->avg_diff_total = diffsum / pixels;
+  props->avg_diff_total = diffsum / (result->width * result->height);
 
   return TRUE;
 }
@@ -202,15 +168,16 @@ gegl_chant_class_init (GeglChantClass *klass)
 
   operation_class->prepare                 = prepare;
   operation_class->get_required_for_output = get_required_for_output;
+  operation_class->get_cached_region       = get_cached_region;
   composer_class->process                  = process;
 
   gegl_operation_class_set_keys (operation_class,
-                                 "name"       , "gegl:image-compare",
-                                 "categories" , "programming",
-                                 "description", _("Compares if input and aux buffers are "
-                                                  "different. Results are saved in the "
-                                                  "properties."),
-                                 NULL);
+    "name"       , "gegl:image-compare",
+    "categories" , "programming",
+    "description", _("Compares if input and aux buffers are "
+                     "different. Results are saved in the "
+                     "properties."),
+    NULL);
 }
 
 #endif


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