[gegl] cartoon: some improvements



commit 975ac4bd58150376112ef745922498c662e2414b
Author: Thomas Manni <thomas manni free fr>
Date:   Wed Feb 1 19:16:30 2017 +0100

    cartoon: some improvements
    
    Use FILTER base class instead of AREA_FILTER
    Use buffers iterators instead of samplers
    Reduce total number of babl conversions

 operations/common/cartoon.c |  192 +++++++++++++++++++------------------------
 1 files changed, 86 insertions(+), 106 deletions(-)
---
diff --git a/operations/common/cartoon.c b/operations/common/cartoon.c
index 2ed49e9..4f0ea95 100644
--- a/operations/common/cartoon.c
+++ b/operations/common/cartoon.c
@@ -30,7 +30,7 @@ property_double (pct_black, _("Percent black"), 0.2)
 
 #else
 
-#define GEGL_OP_AREA_FILTER
+#define GEGL_OP_FILTER
 #define GEGL_OP_NAME     cartoon
 #define GEGL_OP_C_SOURCE cartoon.c
 
@@ -101,51 +101,48 @@ grey_blur_buffer (GeglBuffer  *input,
 }
 
 static gdouble
-compute_ramp (GeglSampler         *sampler1,
-              GeglSampler         *sampler2,
-              const GeglRectangle *roi,
-              gdouble              pct_black)
+compute_ramp (GeglBuffer  *dest1,
+              GeglBuffer  *dest2,
+              gdouble      pct_black)
 {
+  GeglBufferIterator *iter;
   gint    hist[100];
-  gdouble diff;
   gint    count;
-  gfloat pixel1, pixel2;
-  gint x;
-  gint y;
   gint i;
   gint sum;
 
   memset (hist, 0, sizeof (int) * 100);
   count = 0;
 
-  for (y = roi->y; y < roi->y + roi->height; ++y)
-    for (x = roi->x; x < roi->x + roi->width; ++x)
-      {
-        gegl_sampler_get (sampler1,
-                          x,
-                          y,
-                          NULL,
-                          &pixel1,
-                          GEGL_ABYSS_NONE);
-
-        gegl_sampler_get (sampler2,
-                          x,
-                          y,
-                          NULL,
-                          &pixel2,
-                          GEGL_ABYSS_NONE);
-
-        if (pixel2 != 0)
-          {
-            diff = (gdouble) pixel1 / (gdouble) pixel2;
-
-            if (diff < 1.0 && diff >= 0.0)
-              {
-                hist[(int) (diff * 100)] += 1;
-                count += 1;
-              }
-          }
+  iter = gegl_buffer_iterator_new (dest1, NULL, 0, babl_format ("Y' float"),
+                                   GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, dest2, NULL, 0, babl_format ("Y' float"),
+                            GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+  while (gegl_buffer_iterator_next (iter))
+    {
+      gfloat *pixel1   = iter->data[0];
+      gfloat *pixel2   = iter->data[1];
+      glong   n_pixels = iter->length;
+
+      while (n_pixels--)
+        {
+          if (*pixel2 != 0)
+            {
+              gdouble diff = (gdouble) *pixel1 / (gdouble) *pixel2;
+
+              if (diff < 1.0 && diff >= 0.0)
+                {
+                  hist[(int) (diff * 100)] += 1;
+                  count += 1;
+                }
+            }
+
+          pixel1++;
+          pixel2++;
       }
+  }
 
   if (pct_black == 0.0 || count == 0)
     return 1.0;
@@ -159,16 +156,13 @@ compute_ramp (GeglSampler         *sampler1,
     }
 
   return 0.0;
-
 }
 
 static void
 prepare (GeglOperation *operation)
 {
-  gegl_operation_set_format (operation, "input",
-                             babl_format ("Y'CbCrA float"));
-  gegl_operation_set_format (operation, "output",
-                             babl_format ("Y'CbCrA float"));
+  gegl_operation_set_format (operation, "input",  babl_format ("RGBA float"));
+  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
 }
 
 static GeglRectangle
@@ -220,35 +214,28 @@ process (GeglOperation       *operation,
   GeglBufferIterator *iter;
   GeglBuffer         *dest1;
   GeglBuffer         *dest2;
-  GeglSampler        *sampler1;
-  GeglSampler        *sampler2;
   gdouble             ramp;
-  gint                x;
-  gint                y;
-  gfloat              tot_pixels = result->width * result->height;
-  gfloat              pixels = 0;
+  gdouble             progress = 0.0;
+  gdouble             pixels_count = result->width * result->height;
 
   grey_blur_buffer (input, o->mask_radius, &dest1, &dest2);
 
-  sampler1 = gegl_buffer_sampler_new_at_level (dest1,
-                                               babl_format ("Y' float"),
-                                               GEGL_SAMPLER_LINEAR,
-                                               level);
-
-  sampler2 = gegl_buffer_sampler_new_at_level (dest2,
-                                               babl_format ("Y' float"),
-                                               GEGL_SAMPLER_LINEAR,
-                                               level);
-
-  ramp = compute_ramp (sampler1, sampler2, result, o->pct_black);
+  ramp = compute_ramp (dest1, dest2, o->pct_black);
 
   iter = gegl_buffer_iterator_new (output, result, 0,
                                    babl_format ("Y'CbCrA float"),
                                    GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+
   gegl_buffer_iterator_add (iter, input, result, 0,
                             babl_format ("Y'CbCrA float"),
                             GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
 
+  gegl_buffer_iterator_add (iter, dest1, NULL, 0, babl_format ("Y' float"),
+                            GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
+  gegl_buffer_iterator_add (iter, dest2, NULL, 0, babl_format ("Y' float"),
+                            GEGL_ACCESS_READ, GEGL_ABYSS_NONE);
+
 
   gegl_operation_progress (operation, 0.0, "");
 
@@ -256,57 +243,47 @@ process (GeglOperation       *operation,
     {
       gfloat *out_pixel = iter->data[0];
       gfloat *in_pixel  = iter->data[1];
-
-      for (y = iter->roi[0].y; y < iter->roi[0].y + iter->roi[0].height; ++y)
-      {
-        for (x = iter->roi[0].x; x < iter->roi[0].x + iter->roi[0].width; ++x)
-          {
-            gfloat  pixel1;
-            gfloat  pixel2;
-            gdouble mult = 0.0;
-            gdouble diff;
-
-            gegl_sampler_get (sampler1, x, y,
-                              NULL, &pixel1,
-                              GEGL_ABYSS_NONE);
-
-            gegl_sampler_get (sampler2, x, y,
-                              NULL, &pixel2,
-                              GEGL_ABYSS_NONE);
-
-            if (pixel2 != 0)
-              {
-                diff = (gdouble) pixel1 / (gdouble) pixel2;
-                if (diff < THRESHOLD)
-                  {
-                    if (GEGL_FLOAT_EQUAL (ramp, 0.0))
-                      mult = 0.0;
-                    else
-                      mult = (ramp - MIN (ramp, (THRESHOLD - diff))) / ramp;
-                  }
-                else
-                  mult = 1.0;
-              }
-
-            out_pixel[0] = CLAMP (pixel1 * mult, 0.0, 1.0);
-            out_pixel[1] = in_pixel[1];
-            out_pixel[2] = in_pixel[2];
-            out_pixel[3] = in_pixel[3];
-
-            out_pixel += 4;
-            in_pixel  += 4;
-
-          }
-        pixels += iter->roi[0].width;
-        gegl_operation_progress (operation, pixels / tot_pixels, "");
-      }
+      gfloat *grey1     = iter->data[2];
+      gfloat *grey2     = iter->data[3];
+      glong   n_pixels  = iter->length;
+
+      progress += n_pixels / pixels_count;
+
+      while (n_pixels--)
+        {
+          gdouble mult = 0.0;
+
+          if (*grey2 != 0)
+            {
+              gdouble diff = (gdouble) *grey1 / (gdouble) *grey2;
+
+              if (diff < THRESHOLD)
+                {
+                  if (GEGL_FLOAT_EQUAL (ramp, 0.0))
+                    mult = 0.0;
+                  else
+                    mult = (ramp - MIN (ramp, (THRESHOLD - diff))) / ramp;
+                }
+              else
+                mult = 1.0;
+            }
+
+          out_pixel[0] = CLAMP (*grey1 * mult, 0.0, 1.0);
+          out_pixel[1] = in_pixel[1];
+          out_pixel[2] = in_pixel[2];
+          out_pixel[3] = in_pixel[3];
+
+          out_pixel += 4;
+          in_pixel  += 4;
+          grey1++;
+          grey2++;
+        }
+
+        gegl_operation_progress (operation, progress, "");
     }
 
   gegl_operation_progress (operation, 1.0, "");
 
-  g_object_unref (sampler1);
-  g_object_unref (sampler2);
-
   g_object_unref (dest1);
   g_object_unref (dest2);
 
@@ -335,7 +312,10 @@ gegl_op_class_init (GeglOpClass *klass)
     "name",        "gegl:cartoon",
     "title",       _("Cartoon"),
     "license",     "GPL3+",
-    "description", _("Simulates a cartoon, its result is similar to a black felt pen drawing subsequently 
shaded with color. This is achieved by enhancing edges and darkening areas that are already distinctly darker 
than their neighborhood"),
+    "description", _("Simulates a cartoon, its result is similar to a black"
+                     " felt pen drawing subsequently shaded with color. This"
+                     " is achieved by enhancing edges and darkening areas that"
+                     " are already distinctly darker than their neighborhood"),
     NULL);
 }
 


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