[gegl] bloom: add new operation to the workshop
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] bloom: add new operation to the workshop
- Date: Sun, 22 Mar 2020 23:26:24 +0000 (UTC)
commit 84d79f2fbacaec234987c3bbc0c5ddc409ccac2d
Author: Ell <ell_se yahoo com>
Date: Mon Mar 23 01:24:41 2020 +0200
bloom: add new operation to the workshop
gegl:bloom adds a glow around bright areas of the image.
operations/workshop/bloom.c | 229 ++++++++++++++++++++++++++++++++++++++++
operations/workshop/meson.build | 1 +
po/POTFILES.in | 1 +
3 files changed, 231 insertions(+)
---
diff --git a/operations/workshop/bloom.c b/operations/workshop/bloom.c
new file mode 100644
index 000000000..90aba4903
--- /dev/null
+++ b/operations/workshop/bloom.c
@@ -0,0 +1,229 @@
+/* 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 Ell
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#define EPSILON 1e-6
+
+#ifdef GEGL_PROPERTIES
+
+property_double (amount, _("Amount"), 50.0)
+ description (_("Glow-area brightness threshold"))
+ value_range (0.0, 100.0)
+
+property_double (softness, _("Softness"), 25.0)
+ description (_("Glow-area edge softness"))
+ value_range (0.0, 100.0)
+
+property_double (radius, _("Radius"), 10.0)
+ description (_("Glow radius"))
+ value_range (0.0, 1500.0)
+ ui_range (0.0, 100.0)
+ ui_gamma (2.0)
+ ui_meta ("unit", "pixel-distance")
+
+property_double (strength, _("Strength"), 50.0)
+ description (_("Glow strength"))
+ value_range (0.0, 1000.0)
+ ui_range (0.0, 100.0)
+
+#else
+
+#define GEGL_OP_META
+#define GEGL_OP_NAME bloom
+#define GEGL_OP_C_SOURCE bloom.c
+
+#include "gegl-op.h"
+
+typedef struct
+{
+ GeglNode *convert_format;
+ GeglNode *cast_format;
+ GeglNode *levels;
+ GeglNode *rgb_clip;
+ GeglNode *multiply;
+ GeglNode *gaussian_blur;
+ GeglNode *add;
+} Nodes;
+
+static void
+update (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ Nodes *nodes = o->user_data;
+
+ if (nodes)
+ {
+ gdouble threshold = 1.0 - o->amount / 100.0;
+
+ gegl_node_set (nodes->levels,
+ "in-low", threshold - o->softness / 100.0,
+ "in-high", threshold + o->softness / 100.0,
+ "out-high", o->strength / 100.0,
+ NULL);
+
+ gegl_node_set (nodes->rgb_clip,
+ "high-limit", o->strength / 100.0,
+ NULL);
+ }
+}
+
+static void
+attach (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ GeglNode *input;
+ GeglNode *output;
+ Nodes *nodes;
+
+ input = gegl_node_get_input_proxy (operation->node, "input");
+ output = gegl_node_get_output_proxy (operation->node, "output");
+
+ if (! o->user_data)
+ o->user_data = g_slice_new (Nodes);
+
+ nodes = o->user_data;
+
+ nodes->convert_format = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:convert-format",
+ "format", babl_format ("Y float"),
+ NULL);
+
+ nodes->cast_format = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:cast-format",
+ "input-format", babl_format ("Y' float"),
+ "output-format", babl_format ("Y float"),
+ NULL);
+
+ nodes->levels = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:levels",
+ NULL);
+
+ nodes->rgb_clip = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:rgb-clip",
+ NULL);
+
+ nodes->multiply = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:multiply",
+ NULL);
+
+ nodes->gaussian_blur = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:gaussian-blur",
+ NULL);
+
+ nodes->add = gegl_node_new_child (
+ operation->node,
+ "operation", "gegl:add",
+ NULL);
+
+ gegl_node_link_many (input,
+ nodes->convert_format,
+ nodes->cast_format,
+ nodes->levels,
+ nodes->rgb_clip,
+ NULL);
+
+ gegl_node_connect_to (input, "output",
+ nodes->multiply, "input");
+ gegl_node_connect_to (nodes->rgb_clip, "output",
+ nodes->multiply, "aux");
+
+ gegl_node_link (nodes->multiply, nodes->gaussian_blur);
+
+ gegl_node_connect_to (input, "output",
+ nodes->add, "input");
+ gegl_node_connect_to (nodes->gaussian_blur, "output",
+ nodes->add, "aux");
+
+ gegl_node_link (nodes->add, output);
+
+ gegl_operation_meta_redirect (operation, "radius",
+ nodes->gaussian_blur, "std-dev-x");
+ gegl_operation_meta_redirect (operation, "radius",
+ nodes->gaussian_blur, "std-dev-y");
+
+ gegl_operation_meta_watch_nodes (operation,
+ nodes->convert_format,
+ nodes->cast_format,
+ nodes->levels,
+ nodes->rgb_clip,
+ nodes->multiply,
+ nodes->gaussian_blur,
+ nodes->add,
+ NULL);
+
+ update (operation);
+}
+
+static void
+my_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ set_property (object, property_id, value, pspec);
+
+ update (GEGL_OPERATION (object));
+}
+
+static void
+dispose (GObject *object)
+{
+ GeglProperties *o = GEGL_PROPERTIES (object);
+
+ if (o->user_data)
+ {
+ g_slice_free (Nodes, o->user_data);
+
+ o->user_data = NULL;
+ }
+
+ 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);
+ operation_class = GEGL_OPERATION_CLASS (klass);
+
+ object_class->dispose = dispose;
+ object_class->set_property = my_set_property;
+
+ operation_class->attach = attach;
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:bloom",
+ "title", _("Bloom"),
+ "categories", "light",
+ "description", _("Add glow around bright areas"),
+ NULL);
+}
+
+#endif
diff --git a/operations/workshop/meson.build b/operations/workshop/meson.build
index 8d8bbab05..b9600ff41 100644
--- a/operations/workshop/meson.build
+++ b/operations/workshop/meson.build
@@ -5,6 +5,7 @@ libraries = [
{ 'name': 'aces-rrt', },
{ 'name': 'alpha-inpaint', },
{ 'name': 'bilateral-filter-fast', },
+ { 'name': 'bloom', },
{ 'name': 'boxblur-1d', },
{ 'name': 'boxblur', },
{ 'name': 'connected-components', },
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 0a15b749b..f730ac868 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -260,6 +260,7 @@ operations/transform/transform-core.c
operations/transform/translate.c
operations/workshop/aces-rrt.c
operations/workshop/bilateral-filter-fast.c
+operations/workshop/bloom.c
operations/workshop/boxblur-1d.c
operations/workshop/boxblur.c
operations/workshop/connected-components.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]