[gegl] workshop: add edges and details op
- From: Øyvind "pippin" Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] workshop: add edges and details op
- Date: Sat, 9 May 2020 10:06:24 +0000 (UTC)
commit a1b14f12ebf736b47920208e77a0d1d7aac26409
Author: Øyvind Kolås <pippin gimp org>
Date: Sat May 9 12:04:29 2020 +0200
workshop: add edges and details op
A new meta-op that permits does a dual band-pass enhancement for
noise reduction and edge boosting.
operations/workshop/edges-and-details.c | 190 ++++++++++++++++++++++++++++++++
operations/workshop/meson.build | 1 +
2 files changed, 191 insertions(+)
---
diff --git a/operations/workshop/edges-and-details.c b/operations/workshop/edges-and-details.c
new file mode 100644
index 000000000..285ce72a0
--- /dev/null
+++ b/operations/workshop/edges-and-details.c
@@ -0,0 +1,190 @@
+/* This file is an image processing operation for GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * Copyright 2020 Øyvind Kolås <pippin gimp org>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_double (radius1, _("Detail band"), 1.1)
+ description(_("Features size for detail band, used for noise removal."))
+ value_range (0.0, 100.0)
+ ui_range (0.5, 2.0)
+ ui_meta ("unit", "pixel-distance")
+
+property_double (scale1, _("Detail scale, negative values dimnishes signal in detail band, postivie values
increases signal."), -1.6)
+ description(_("Scaling factor for image features at radius, -1 cancels them out 1.0 edge enhances"))
+ value_range (-3.0, 100.0)
+ ui_range (-3.0, 3.0)
+
+property_double (radius2, _("Feature band"), 4.0)
+ description(_("Expressed as standard deviation, in pixels"))
+ value_range (0.0, 100.0)
+ ui_range (0.5, 20.0)
+ ui_meta ("unit", "pixel-distance")
+
+property_double (scale2, _("Feature scale"), 0.0)
+ description(_("Scaling factor for image features at radius, -1 cancels them out 1.0 edge enhances, when
set to 0.0 performance of op is higher."))
+ value_range (-3.0, 100.0)
+ ui_range (-3.0, 3.0)
+
+#else
+
+#define GEGL_OP_META
+#define GEGL_OP_NAME edges_and_details
+#define GEGL_OP_C_SOURCE edges-and-details.c
+
+#include "gegl-op.h"
+
+typedef struct
+{
+ GeglNode *input;
+ GeglNode *add1;
+ GeglNode *dog1;
+ GeglNode *mul1;
+ GeglNode *add2;
+ GeglNode *dog2;
+ GeglNode *mul2;
+ GeglNode *output;
+} State;
+
+static float compute_radius2 (float center_radius, float bw)
+{
+ return center_radius / (bw + 1);
+}
+static float compute_radius1 (float center_radius, float bw)
+{
+ return compute_radius2(center_radius, bw) * bw;
+}
+
+static void
+update_graph (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ State *state = o->user_data;
+ if (!state) return;
+ float bw = 0.625;
+ GeglNode *iter = state->input;
+
+ if (fabs(o->scale1) > 0.01)
+ {
+ float radius1 = compute_radius1(o->radius1, bw);
+ float radius2 = compute_radius2(o->radius1, bw);
+ gegl_node_set (state->dog1, "radius1", radius1,
+ "radius2", radius2,
+ NULL);
+ gegl_node_set (state->mul1, "value", o->scale1, NULL);
+ gegl_node_connect_from (state->add1, "input",
+ iter, "output");
+ gegl_node_connect_from (state->dog1, "input",
+ iter, "output");
+ gegl_node_connect_from (state->mul1, "input",
+ state->dog1, "output");
+ gegl_node_connect_from (state->add1, "aux",
+ state->mul1, "output");
+ iter = state->add1;
+ }
+ if (fabs (o->scale2) > 0.01)
+ {
+ float radius1 = compute_radius1(o->radius2, bw);
+ float radius2 = compute_radius2(o->radius2, bw);
+ gegl_node_set (state->dog2, "radius1", radius1,
+ "radius2", radius2,
+ NULL);
+ gegl_node_set (state->mul2, "value", o->scale2, NULL);
+ gegl_node_connect_from (state->add2, "input",
+ iter, "output");
+ gegl_node_connect_from (state->dog2, "input",
+ iter, "output");
+ gegl_node_connect_from (state->mul2, "input",
+ state->dog2, "output");
+ gegl_node_connect_from (state->add2, "aux",
+ state->mul2, "output");
+ iter = state->add2;
+ }
+ gegl_node_connect_from (state->output, "input",
+ iter, "output");
+}
+
+static void
+attach (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ GeglNode *gegl = operation->node;
+ State *state = g_malloc0 (sizeof (State));
+ o->user_data = state;
+
+ state->input = gegl_node_get_input_proxy (gegl, "input");
+ state->output = gegl_node_get_output_proxy (gegl, "output");
+ state->add1 = gegl_node_new_child (gegl, "operation", "gegl:add", NULL);
+ state->mul1 = gegl_node_new_child (gegl, "operation", "gegl:multiply", "value", 0.0, NULL);
+ state->dog1 = gegl_node_new_child (gegl, "operation", "gegl:difference-of-gaussians", NULL);
+
+ state->add2 = gegl_node_new_child (gegl, "operation", "gegl:add", NULL);
+ state->mul2 = gegl_node_new_child (gegl, "operation", "gegl:multiply", "value", 0.0, NULL);
+ state->dog2 = gegl_node_new_child (gegl, "operation", "gegl:difference-of-gaussians", NULL);
+
+ update_graph (operation);
+}
+
+static void
+my_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeglProperties *o = GEGL_PROPERTIES (object);
+
+ set_property (object, property_id, value, pspec);
+
+ if (o)
+ update_graph ((void*)object);
+}
+
+static void
+dispose (GObject *object)
+{
+ GeglProperties *o = GEGL_PROPERTIES (object);
+ g_clear_pointer (&o->user_data, g_free);
+ G_OBJECT_CLASS (gegl_op_parent_class)->dispose (object);
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GObjectClass *object_class;
+ GeglOperationClass *operation_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->dispose = dispose;
+ object_class->set_property = my_set_property;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+
+ operation_class->attach = attach;
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:edges-and-details",
+ "title", _("Edges and Details"),
+ "categories", "enhance:sharpen:denoise",
+ "description", _("Two band parametric equalizer, for noise reduction and edge enhancement."),
+ NULL);
+}
+
+#endif
diff --git a/operations/workshop/meson.build b/operations/workshop/meson.build
index 8d8bbab05..3f1147c9d 100644
--- a/operations/workshop/meson.build
+++ b/operations/workshop/meson.build
@@ -11,6 +11,7 @@ libraries = [
{ 'name': 'demosaic-bimedian', },
{ 'name': 'demosaic-simple', },
{ 'name': 'ditto', },
+ { 'name': 'edges-and-details', },
{ 'name': 'gcr', },
{ 'name': 'gradient-map', },
{ 'name': 'hstack', },
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]