[gegl] workshop: add a way to enlarge the output extent for gaussian blur
- From: Téo Mazars <teom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] workshop: add a way to enlarge the output extent for gaussian blur
- Date: Sun, 5 Jan 2014 12:31:29 +0000 (UTC)
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]