[gegl] color-assimilation-grid: an operation to render a perceptual illusion



commit 5048642f967dcd920c4d681d00badce268b19d53
Author: Øyvind Kolås <pippin gimp org>
Date:   Mon Jul 29 14:31:05 2019 +0200

    color-assimilation-grid: an operation to render a perceptual illusion
    
    Turns image grayscale and overlay an oversaturated grid - through color
    assimilation happening in the human visual system, for some grid scales this
    produces the illusion that the grayscale grid cells themselves also have color.

 operations/common/Makefile.am               |   1 +
 operations/common/color-assimilation-grid.c | 170 ++++++++++++++++++++++++++++
 po/POTFILES.in                              |   1 +
 3 files changed, 172 insertions(+)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index a3491b514..23b553ab9 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -25,6 +25,7 @@ gegl_common_la_SOURCES =\
        c2g.c \
        checkerboard.c \
        dither.c \
+       color-assimilation-grid.c \
        color-enhance.c \
        color-overlay.c \
        color-rotate.c \
diff --git a/operations/common/color-assimilation-grid.c b/operations/common/color-assimilation-grid.c
new file mode 100644
index 000000000..933bf112f
--- /dev/null
+++ b/operations/common/color-assimilation-grid.c
@@ -0,0 +1,170 @@
+/* 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/>.
+ *
+ * Original idea and concept by Øyvind Kolås
+ * also Copyright 2019 Øyvind Kolås <pippin gimp org>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_double (grid_size, _("Grid size"), 23)
+    value_range (0.0, 150)
+    ui_range    (0.0, 40.0)
+    ui_gamma    (3.0)
+    ui_meta     ("unit", "pixel-distance")
+
+property_double (saturation, _("Saturation"), 2.5)
+    value_range (0.0, 30.0)
+    ui_range    (0.0, 10.0)
+
+property_double (angle, _("Angle"), 45.0)
+    value_range (-180.0, 180.0)
+    ui_range    (-180.0, 180.0)
+    ui_gamma    (1.0)
+
+property_double (line_thickness, _("Line thickness"), 0.4)
+    value_range (0.0, 1.0)
+    ui_range    (0.0, 1.0)
+    ui_gamma    (1.0)
+
+#else
+
+#define GEGL_OP_META
+#define GEGL_OP_NAME     color_assimilation_grid
+#define GEGL_OP_C_SOURCE color-assimilation-grid.c
+
+#include "gegl-op.h"
+
+typedef struct
+{
+  GeglNode *desaturate;
+  GeglNode *saturate;
+  GeglNode *over;
+  GeglNode *opacity;
+  GeglNode *mask;
+  GeglNode *color;
+  double    old_line_thickness;
+} State;
+
+static void
+update_graph (GeglOperation *operation)
+{
+  GeglProperties *o = GEGL_PROPERTIES (operation);
+  State *s = o->user_data;
+  if (s && s->old_line_thickness != o->line_thickness)
+  {
+    GeglColor *color = gegl_color_new (NULL);
+    gegl_color_set_rgba (color, o->line_thickness,
+                                o->line_thickness,
+                                o->line_thickness, 1.0);
+    gegl_node_set (s->color, "value", color, NULL);
+    g_object_unref (color);
+    s->old_line_thickness = o->line_thickness;
+  }
+
+}
+
+static void
+attach (GeglOperation *operation)
+{
+  GeglProperties *o = GEGL_PROPERTIES (operation);
+  State          *s = g_malloc0 (sizeof (State));
+  GeglNode       *gegl, *input, *output;
+
+  o->user_data = s;
+  gegl = operation->node;
+
+  s->desaturate   = gegl_node_new_child (gegl, "operation", "gegl:saturation",
+                                               "scale", 0.0, NULL);
+  s->saturate     = gegl_node_new_child (gegl, "operation", "gegl:saturation",
+                                               "scale", 0.0, NULL);
+  s->over         = gegl_node_new_child (gegl, "operation", "gegl:over", NULL);
+  s->opacity      = gegl_node_new_child (gegl, "operation", "gegl:opacity",
+                                               "value", 1.0, NULL);
+  s->mask = gegl_node_new_child (gegl, "operation", "gegl:newsprint",
+                                               "pattern", 4,
+                                                "angle",  o->angle,
+                                                "period", o->grid_size,
+                                                "color-model", 0, NULL);
+  s->color        = gegl_node_new_child (gegl, "operation", "gegl:color",
+                                               NULL);
+
+  input           = gegl_node_get_input_proxy  (gegl, "input");
+  output          = gegl_node_get_output_proxy (gegl, "output");
+
+  gegl_node_link_many (input, s->desaturate, s->over, output, NULL);
+  gegl_node_link_many (input, s->saturate, s->opacity, NULL);
+  gegl_node_link_many (s->color, s->mask, NULL);
+
+  gegl_node_connect_from (s->opacity, "aux", s->mask,  "output");
+  gegl_node_connect_from (s->over,    "aux", s->opacity,  "output");
+
+  gegl_operation_meta_redirect (operation, "grid-size", s->mask, "period");
+  gegl_operation_meta_redirect (operation, "angle", s->mask, "angle");
+  gegl_operation_meta_redirect (operation, "saturation", s->saturate, "scale");
+
+  gegl_operation_meta_watch_nodes (operation, s->mask, s->saturate, 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:color-assimilation-grid",
+    "title",       _("Color Assimilation Grid)"),
+    "categories",  "illusions",
+    "description", _("Turn image grayscale and overlay an oversaturated grid - through color assimilation 
happening in the human visual system, for some grid scales this produces the illusion that the grayscale grid 
cells themselves also have color."),
+    NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 7ddbb2ded..2ec85ad69 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -22,6 +22,7 @@ operations/common/buffer-source.c
 operations/common/c2g.c
 operations/common/checkerboard.c
 operations/common/color.c
+operations/common/color-assimilation-grid.c
 operations/common/color-enhance.c
 operations/common/color-overlay.c
 operations/common/color-rotate.c


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