[gegl] photocopy: Don't linearize, implement get_cached_region



commit fa0b423c707f44a9c5166573488f2e574d9b4872
Author: Daniel Sabo <DanielSabo gmail com>
Date:   Tue Mar 18 23:56:50 2014 -0700

    photocopy: Don't linearize, implement get_cached_region

 operations/common/photocopy.c |  324 ++++++++++++++++-------------------------
 1 files changed, 128 insertions(+), 196 deletions(-)
---
diff --git a/operations/common/photocopy.c b/operations/common/photocopy.c
index f49b5b3..0e28656 100644
--- a/operations/common/photocopy.c
+++ b/operations/common/photocopy.c
@@ -48,15 +48,6 @@ gegl_chant_double (white, _("Percent White"),
 
 #define THRESHOLD 0.75
 
-typedef struct {
-  gdouble      black;
-  gdouble      white;
-  gdouble      prev_mask_radius;
-  gdouble      prev_sharpness;
-  gdouble      prev_black;
-  gdouble      prev_white;
-} Ramps;
-
 static void
 grey_blur_buffer (GeglBuffer  *input,
                   gdouble      sharpness,
@@ -137,83 +128,66 @@ calculate_threshold (gint    *hist,
 }
 
 static void
-compute_ramp (GeglBuffer    *input,
-              GeglOperation *operation,
-              gdouble        pct_black,
-              gdouble        pct_white,
-              gint           under_threshold,
-              gdouble       *threshold_black,
-              gdouble       *threshold_white)
+compute_ramp (GeglBuffer          *dest1,
+              GeglBuffer          *dest2,
+              const GeglRectangle *roi,
+              gdouble              pct_black,
+              gdouble              pct_white,
+              gboolean             under_threshold,
+              gdouble             *threshold_black,
+              gdouble             *threshold_white)
 {
-  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+  GeglBufferIterator *iter;
 
-  GeglRectangle *whole_region;
-  gint    n_pixels;
   gint    hist1[2000];
   gint    hist2[2000];
   gdouble diff;
   gint    count;
-  GeglBuffer *dest1, *dest2;
-
-  gfloat *src1_buf;
-  gfloat *src2_buf;
-  gfloat *dst_buf;
-
-  gint total_pixels;
-
-  gfloat* ptr1;
-  gfloat* ptr2;
 
-  whole_region = gegl_operation_source_get_bounding_box (operation, "input");
-  grey_blur_buffer (input, o->sharpness, o->mask_radius, &dest1, &dest2);
-
-  total_pixels = whole_region->width * whole_region->height;
-  src1_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-  src2_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-  dst_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
-  gegl_buffer_get (dest1, whole_region, 1.0, babl_format ("Y float"),
-                   src1_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-  gegl_buffer_get (dest2, whole_region, 1.0, babl_format ("Y float"),
-                   src2_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-
-  n_pixels = whole_region->width * whole_region->height;
+  iter = gegl_buffer_iterator_new (dest1, roi, 0,
+                                   babl_format ("Y float"),
+                                   GEGL_BUFFER_READ,
+                                   GEGL_ABYSS_NONE);
+  gegl_buffer_iterator_add (iter, dest2, roi, 0,
+                            babl_format ("Y float"),
+                            GEGL_BUFFER_READ,
+                            GEGL_ABYSS_NONE);
 
   memset (hist1, 0, sizeof (int) * 2000);
   memset (hist2, 0, sizeof (int) * 2000);
   count = 0;
-  ptr1 = src1_buf;
-  ptr2 = src2_buf;
-  while (n_pixels--)
-    {
-      diff = *ptr1 / *ptr2;
-      ptr1++;
-      ptr2++;
-      if (under_threshold)
-        {
-          if (diff < THRESHOLD)
-            {
-              hist2[(int) (diff * 1000)] ++;
-              count ++;
-            }
-        }
-      else
-        {
-          if (diff >= THRESHOLD && diff < 2.0)
-            {
-              hist1[(int) (diff * 1000)] ++;
-              count ++;
-            }
-        }
 
-    }
-
-  g_object_unref (dest1);
-  g_object_unref (dest2);
-
-  g_slice_free1 (total_pixels * sizeof (gfloat), src1_buf);
-  g_slice_free1 (total_pixels * sizeof (gfloat), src2_buf);
-  g_slice_free1 (total_pixels * sizeof (gfloat), dst_buf);
+  while (gegl_buffer_iterator_next (iter))
+  {
+    gint n_pixels = iter->length;
+    gfloat *ptr1  = iter->data[0];
+    gfloat *ptr2  = iter->data[1];
+
+    while (n_pixels--)
+      {
+        diff = *ptr1 / *ptr2;
+        ptr1++;
+        ptr2++;
+
+        if (under_threshold)
+          {
+            if (diff < THRESHOLD && diff >= 0.0f)
+              {
+                hist2[(int) (diff * 1000)] ++;
+                count ++;
+              }
+          }
+        else
+          {
+            if (diff >= THRESHOLD && diff < 2.0)
+              {
+                hist1[(int) (diff * 1000)] ++;
+                count ++;
+              }
+          }
+
+      }
+  }
 
   *threshold_black = calculate_threshold (hist1, pct_black, count, 0);
   *threshold_white = calculate_threshold (hist2, pct_white, count, 1);
@@ -222,26 +196,36 @@ compute_ramp (GeglBuffer    *input,
 static void
 prepare (GeglOperation *operation)
 {
-  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
-
   gegl_operation_set_format (operation, "input",
                              babl_format ("Y float"));
   gegl_operation_set_format (operation, "output",
                              babl_format ("Y float"));
-  if (o->chant_data)
-    {
-      Ramps* ramps = (Ramps*) o->chant_data;
+}
 
-      /* hack so that thresholds are only calculated once */
-      if (ramps->prev_mask_radius != o->mask_radius ||
-          ramps->prev_sharpness   != o->sharpness   ||
-          ramps->prev_black       != o->black       ||
-          ramps->prev_white       != o->white)
-        {
-          g_slice_free (Ramps, o->chant_data);
-          o->chant_data = NULL;
-        }
-    }
+static GeglRectangle
+get_required_for_output (GeglOperation       *operation,
+                         const gchar         *input_pad,
+                         const GeglRectangle *roi)
+{
+  GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+  /* Don't request an infinite plane */
+  if (gegl_rectangle_is_infinite_plane (&result))
+    return *roi;
+
+  return result;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation       *operation,
+                   const GeglRectangle *roi)
+{
+  GeglRectangle result = *gegl_operation_source_get_bounding_box (operation, "input");
+
+  if (gegl_rectangle_is_infinite_plane (&result))
+    return *roi;
+
+  return result;
 }
 
 static gboolean
@@ -253,144 +237,92 @@ process (GeglOperation       *operation,
 {
   GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
 
+  GeglBufferIterator *iter;
+
   GeglBuffer *dest1;
   GeglBuffer *dest2;
 
-  Ramps* ramps;
-
-  gint n_pixels;
-  gfloat *out_pixel;
-  gint total_pixels;
-
   gdouble diff;
-  Ramps *get_ramps;
   gdouble ramp_down;
   gdouble ramp_up;
   gdouble mult;
 
-  gfloat *src1_buf;
-  gfloat *src2_buf;
-  gfloat *dst_buf;
-
-  gfloat* ptr1;
-  gfloat* ptr2;
-
-  static GMutex mutex = { 0, };
-
-  total_pixels = result->width * result->height;
-  dst_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
-  g_mutex_lock (&mutex);
-  if (o->chant_data == NULL)
-    {
-      o->chant_data = g_slice_new (Ramps);
-      ramps = (Ramps*) o->chant_data;
-      compute_ramp (input,
-                    operation,
-                    o->black,
-                    o->white,1,
-                    &ramps->black,
-                    &ramps->white);
-      ramps->prev_mask_radius = o->mask_radius;
-      ramps->prev_sharpness   = o->sharpness;
-      ramps->prev_black       = o->black;
-      ramps->prev_white       = o->white;
-    }
-  g_mutex_unlock (&mutex);
-
   grey_blur_buffer (input, o->sharpness, o->mask_radius, &dest1, &dest2);
 
-  total_pixels = result->width * result->height;
-  src1_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-  src2_buf = g_slice_alloc (total_pixels * sizeof (gfloat));
-
-  gegl_buffer_get (dest1, result, 1.0, babl_format ("Y float"),
-                   src1_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-  gegl_buffer_get (dest2, result, 1.0, babl_format ("Y float"),
-                   src2_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
-  g_object_unref (dest1);
-  g_object_unref (dest2);
-
-  out_pixel = dst_buf;
-  n_pixels = result->width * result->height;
-
-  get_ramps = (Ramps*) o->chant_data;
-  ramp_down = get_ramps->black;
-  ramp_up = get_ramps->white;
-
-  ptr1 = src1_buf;
-  ptr2 = src2_buf;
-
-  while (n_pixels--)
+  compute_ramp (dest1, dest2, result,
+                o->black, o->white, TRUE,
+                &ramp_down, &ramp_up);
+
+  iter = gegl_buffer_iterator_new (dest1, result, 0,
+                                   babl_format ("Y float"),
+                                   GEGL_BUFFER_READ,
+                                   GEGL_ABYSS_NONE);
+  gegl_buffer_iterator_add (iter, dest2, result, 0,
+                            babl_format ("Y float"),
+                            GEGL_BUFFER_READ,
+                            GEGL_ABYSS_NONE);
+  gegl_buffer_iterator_add (iter, output, result, 0,
+                            babl_format ("Y float"),
+                            GEGL_BUFFER_WRITE,
+                            GEGL_ABYSS_NONE);
+
+  while (gegl_buffer_iterator_next (iter))
     {
-      diff = *ptr1 / *ptr2;
-      if (diff < THRESHOLD)
+      gint    n_pixels  = iter->length;
+      gfloat *ptr1      = iter->data[0];
+      gfloat *ptr2      = iter->data[1];
+      gfloat *out_pixel = iter->data[2];
+
+      while (n_pixels--)
         {
-          if (ramp_down == 0.0)
-            *out_pixel = 0.0;
-          else
+          diff = *ptr1 / *ptr2;
+          if (diff < THRESHOLD)
             {
-              mult = (ramp_down - MIN (ramp_down,
-                                       (THRESHOLD - diff))) / ramp_down;
-              *out_pixel = *ptr1 * mult;
+              if (ramp_down == 0.0)
+                *out_pixel = 0.0;
+              else
+                {
+                  mult = (ramp_down - MIN (ramp_down,
+                                           (THRESHOLD - diff))) / ramp_down;
+                  *out_pixel = *ptr1 * mult;
+                }
             }
-        }
-      else
-        {
-          if (ramp_up == 0.0)
-            mult = 1.0;
           else
-            mult = MIN (ramp_up,
-                        (diff - THRESHOLD)) / ramp_up;
+            {
+              if (ramp_up == 0.0)
+                mult = 1.0;
+              else
+                mult = MIN (ramp_up,
+                            (diff - THRESHOLD)) / ramp_up;
 
-          *out_pixel = mult + *ptr1 - mult * *ptr1;
+              *out_pixel = mult + *ptr1 - mult * *ptr1;
+            }
+
+          ptr1++;
+          ptr2++;
+          out_pixel++;
         }
-      ptr1++;
-      ptr2++;
-      out_pixel ++;
     }
 
-  gegl_buffer_set (output,
-                   result,
-                   0,
-                   babl_format ("Y float"),
-                   dst_buf, GEGL_AUTO_ROWSTRIDE);
-
-  g_slice_free1 (total_pixels * sizeof (gfloat), src1_buf);
-  g_slice_free1 (total_pixels * sizeof (gfloat), src2_buf);
-  g_slice_free1 (total_pixels * sizeof (gfloat), dst_buf);
-
-  return  TRUE;
-}
-
-static void
-finalize (GObject *object)
-{
-  GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
-
-  if (o->chant_data)
-    {
-      g_slice_free (Ramps, o->chant_data);
-      o->chant_data = NULL;
-    }
+  g_object_unref (dest1);
+  g_object_unref (dest2);
 
-  G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
+  return TRUE;
 }
 
 static void
 gegl_chant_class_init (GeglChantClass *klass)
 {
-  GObjectClass               *object_class;
   GeglOperationClass       *operation_class;
   GeglOperationFilterClass *filter_class;
 
-  object_class    = G_OBJECT_CLASS (klass);
   operation_class = GEGL_OPERATION_CLASS (klass);
   filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
 
-  object_class->finalize = finalize;
-  operation_class->prepare = prepare;
-  filter_class->process    = process;
+  operation_class->prepare                 = prepare;
+  operation_class->get_required_for_output = get_required_for_output;
+  operation_class->get_cached_region       = get_cached_region;
+  filter_class->process                    = process;
 
   gegl_operation_class_set_keys (operation_class,
     "name",        "gegl:photocopy",


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