[gegl] workshop: add a way to enlarge the output extent for gaussian blur



commit f714a2d33be8dee8879251664def46655d422558
Author: Téo Mazars <teomazars gmail com>
Date:   Sun Jan 5 13:28:11 2014 +0100

    workshop: add a way to enlarge the output extent for gaussian blur

 operations/workshop/gaussian-blur-iir.c |    4 ++
 operations/workshop/gblur-1d.c          |   88 +++++++++++++++++++++++-------
 2 files changed, 71 insertions(+), 21 deletions(-)
---
diff --git a/operations/workshop/gaussian-blur-iir.c b/operations/workshop/gaussian-blur-iir.c
index b9a5f30..0de8dab 100644
--- a/operations/workshop/gaussian-blur-iir.c
+++ b/operations/workshop/gaussian-blur-iir.c
@@ -48,6 +48,8 @@ gegl_chant_enum      (filter, _("Filter"),
 gegl_chant_enum      (abyss_policy, _("Abyss policy"), GeglGaussianBlurPolicy,
                       gegl_gaussian_blur_policy, GEGL_GAUSSIAN_BLUR_ABYSS_NONE,
                       _("How image edges are handled"))
+gegl_chant_boolean   (clip_extent, _("Clip to the input extent"), TRUE,
+                      _("Should the output extent be clipped to the input extent"))
 
 #else
 
@@ -79,10 +81,12 @@ attach (GeglOperation *operation)
   gegl_operation_meta_redirect (operation, "std-dev-x",    hblur, "std-dev");
   gegl_operation_meta_redirect (operation, "abyss-policy", hblur, "abyss-policy");
   gegl_operation_meta_redirect (operation, "filter",       hblur, "filter");
+  gegl_operation_meta_redirect (operation, "clip-extent",  hblur, "clip-extent");
 
   gegl_operation_meta_redirect (operation, "std-dev-y",    vblur, "std-dev");
   gegl_operation_meta_redirect (operation, "abyss-policy", vblur, "abyss-policy");
   gegl_operation_meta_redirect (operation, "filter",       vblur, "filter");
+  gegl_operation_meta_redirect (operation, "clip-extent",  vblur, "clip-extent");
 }
 
 static void
diff --git a/operations/workshop/gblur-1d.c b/operations/workshop/gblur-1d.c
index dd7fdc1..1722d06 100644
--- a/operations/workshop/gblur-1d.c
+++ b/operations/workshop/gblur-1d.c
@@ -59,6 +59,8 @@ gegl_chant_enum      (filter, _("Filter"),
 gegl_chant_enum      (abyss_policy, _("Abyss policy"), GeglGblur1dPolicy,
                       gegl_gblur_1d_policy, GEGL_GBLUR_1D_ABYSS_NONE,
                       _("How image edges are handled"))
+gegl_chant_boolean   (clip_extent, _("Clip to the input extent"), TRUE,
+                      _("Should the output extent be clipped to the input extent"))
 #else
 
 #define GEGL_CHANT_TYPE_FILTER
@@ -578,6 +580,7 @@ filter_disambiguation (GeglGblur1dFilter filter,
 {
   if (filter == GEGL_GBLUR_1D_AUTO)
     {
+      /* Threshold 1.0 is arbitrary */
       if (std_dev < 1.0)
         filter = GEGL_GBLUR_1D_FIR;
       else
@@ -599,6 +602,10 @@ gegl_gblur_1d_prepare (GeglOperation *operation)
   const Babl *src_format = gegl_operation_get_source_format (operation, "input");
   const char *format     = "RaGaBaA float";
 
+  /*
+   * FIXME: when the abyss policy is _NONE, the behavior at the edge
+   *        depends on input format (with or without an alpha component)
+   */
   if (src_format)
     {
       const Babl *model = babl_format_get_model (src_format);
@@ -616,6 +623,28 @@ gegl_gblur_1d_prepare (GeglOperation *operation)
 }
 
 static GeglRectangle
+gegl_gblur_1d_enlarge_extent (GeglChantO          *o,
+                              const GeglRectangle *input_extent)
+{
+  gint clen = fir_calc_convolve_matrix_length (o->std_dev);
+
+  GeglRectangle bounding_box = *input_extent;
+
+  if (o->orientation == GEGL_GBLUR_1D_HORIZONTAL)
+    {
+      bounding_box.x     -= clen / 2;
+      bounding_box.width += clen - 1;
+    }
+  else
+    {
+      bounding_box.y      -= clen / 2;
+      bounding_box.height += clen - 1;
+    }
+
+  return bounding_box;
+}
+
+static GeglRectangle
 gegl_gblur_1d_get_required_for_output (GeglOperation       *operation,
                                        const gchar         *input_pad,
                                        const GeglRectangle *output_roi)
@@ -643,30 +672,45 @@ gegl_gblur_1d_get_required_for_output (GeglOperation       *operation,
               required_for_output.y      = in_rect->y;
               required_for_output.height = in_rect->height;
             }
+
+          if (!o->clip_extent)
+            required_for_output =
+              gegl_gblur_1d_enlarge_extent (o, &required_for_output);
         }
     }
   else
     {
-      gint clen = fir_calc_convolve_matrix_length (o->std_dev);
-
-      required_for_output = *output_roi;
-
-      if (o->orientation == GEGL_GBLUR_1D_HORIZONTAL)
-        {
-          required_for_output.x     -= clen / 2;
-          required_for_output.width += clen - 1;
-        }
-      else
-        {
-          required_for_output.y      -= clen / 2;
-          required_for_output.height += clen - 1;
-        }
+      required_for_output = gegl_gblur_1d_enlarge_extent (o, output_roi);
     }
 
   return required_for_output;
 }
 
 static GeglRectangle
+gegl_gblur_1d_get_bounding_box (GeglOperation *operation)
+{
+  GeglChantO          *o       = GEGL_CHANT_PROPERTIES (operation);
+  const GeglRectangle *in_rect =
+    gegl_operation_source_get_bounding_box (operation, "input");
+
+  if (! in_rect)
+    return *GEGL_RECTANGLE (0, 0, 0, 0);
+
+  if (gegl_rectangle_is_infinite_plane (in_rect))
+    return *in_rect;
+
+  if (o->clip_extent)
+    {
+      return *in_rect;
+    }
+  else
+    {
+      /* We use the FIR convolution length for both the FIR and the IIR case */
+      return gegl_gblur_1d_enlarge_extent (o, in_rect);
+    }
+}
+
+static GeglRectangle
 gegl_gblur_1d_get_cached_region (GeglOperation       *operation,
                                  const GeglRectangle *output_roi)
 {
@@ -676,10 +720,11 @@ gegl_gblur_1d_get_cached_region (GeglOperation       *operation,
 
   if (filter == GEGL_GBLUR_1D_IIR)
     {
-      const GeglRectangle *in_rect =
-        gegl_operation_source_get_bounding_box (operation, "input");
+      const GeglRectangle in_rect =
+        gegl_gblur_1d_get_bounding_box (operation);
 
-      if (in_rect && ! gegl_rectangle_is_infinite_plane (in_rect))
+      if (! gegl_rectangle_is_empty (&in_rect) &&
+          ! gegl_rectangle_is_infinite_plane (&in_rect))
         {
           GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
 
@@ -687,13 +732,13 @@ gegl_gblur_1d_get_cached_region (GeglOperation       *operation,
 
           if (o->orientation == GEGL_GBLUR_1D_HORIZONTAL)
             {
-              cached_region.x     = in_rect->x;
-              cached_region.width = in_rect->width;
+              cached_region.x     = in_rect.x;
+              cached_region.width = in_rect.width;
             }
           else
             {
-              cached_region.y      = in_rect->y;
-              cached_region.height = in_rect->height;
+              cached_region.y      = in_rect.y;
+              cached_region.height = in_rect.height;
             }
         }
     }
@@ -790,6 +835,7 @@ gegl_chant_class_init (GeglChantClass *klass)
 
   filter_class->process                    = gegl_gblur_1d_process;
   operation_class->prepare                 = gegl_gblur_1d_prepare;
+  operation_class->get_bounding_box        = gegl_gblur_1d_get_bounding_box;
   operation_class->get_required_for_output = gegl_gblur_1d_get_required_for_output;
   operation_class->get_cached_region       = gegl_gblur_1d_get_cached_region;
   operation_class->opencl_support          = TRUE;


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