[gegl] bloom: add new operation to the workshop



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]