[gegl] Bug 740540 - Port the gimp Solid Noise plug-in as gegl:noise-solid
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Bug 740540 - Port the gimp Solid Noise plug-in as gegl:noise-solid
- Date: Sat, 22 Nov 2014 20:05:30 +0000 (UTC)
commit c3f3bfc414687d929b934198de7e3422d8cb6fa6
Author: Thomas Manni <thomas manni free fr>
Date: Sat Nov 22 16:28:15 2014 +0100
Bug 740540 - Port the gimp Solid Noise plug-in as gegl:noise-solid
operations/common/Makefile.am | 3 +-
operations/common/noise-solid.c | 332 ++++++++++++++++++++++++++
po/POTFILES.in | 1 +
tests/compositions/Makefile.am | 1 +
tests/compositions/noise-solid.xml | 23 ++
tests/compositions/reference/noise-solid.png | Bin 0 -> 77721 bytes
6 files changed, 359 insertions(+), 1 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index e49b7f1..4402f6e 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -83,7 +83,8 @@ op_LTLIBRARIES = \
noise-rgb.la \
noise-simplex.la \
noise-slur.la \
- noise-spread.la \
+ noise-solid.la \
+ noise-spread.la \
noise-cell.la \
oilify.la \
opacity.la \
diff --git a/operations/common/noise-solid.c b/operations/common/noise-solid.c
new file mode 100644
index 0000000..961b04f
--- /dev/null
+++ b/operations/common/noise-solid.c
@@ -0,0 +1,332 @@
+/* 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 <http://www.gnu.org/licenses/>.
+ *
+ * This operation generates solid noise textures based on the
+ * `Noise' and `Turbulence' functions described in the paper
+ *
+ * Perlin, K, and Hoffert, E. M., "Hypertexture",
+ * Computer Graphics 23, 3 (August 1989)
+ *
+ * The algorithm implemented here also makes possible the
+ * creation of seamless tiles.
+ *
+ * Copyright (C) 1997, 1998 Marcelo de Gomensoro Malheiros
+ *
+ * GEGL port: Thomas Manni <thomas manni free fr>
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_double (x_size, _("X Size"), 4.0)
+ description (_("Horizontal texture size"))
+ ui_range (0.1, 16.0)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "x")
+
+property_double (y_size, _("Y Size"), 4.0)
+ description (_("Vertical texture size"))
+ ui_range (0.1, 16.0)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "y")
+
+property_int (detail, _("Detail"), 1)
+ description (_("Detail level"))
+ ui_range (0, 15)
+ value_range (0, 15)
+
+property_boolean (tilable, _("Tilable"), FALSE)
+ description (_("Create a tilable output"))
+
+property_boolean (turbulent, _("Turbulent"), FALSE)
+ description (_("Make a turbulent noise"))
+
+property_seed (seed, _("Random seed"), rand)
+
+property_int (width, _("Width"), 1024)
+ description (_("Width of the generated buffer"))
+ value_range (0, G_MAXINT)
+ ui_range (0, 4096)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "x")
+ ui_meta ("role", "output-extent")
+
+property_int (height, _("Height"), 768)
+ description(_("Height of the generated buffer"))
+ value_range (0, G_MAXINT)
+ ui_range (0, 4096)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "y")
+ ui_meta ("role", "output-extent")
+
+#else
+
+#define GEGL_OP_POINT_RENDER
+#define GEGL_OP_C_FILE "noise-solid.c"
+
+#include "gegl-op.h"
+
+#define TABLE_SIZE 64
+#define WEIGHT(T) ((2.0 * fabs (T) - 3.0) * (T) * (T) + 1.0)
+
+typedef struct
+{
+ gdouble x;
+ gdouble y;
+} Vector2;
+
+typedef struct
+{
+ gint xclip;
+ gint yclip;
+ gdouble offset;
+ gdouble factor;
+ gdouble xsize;
+ gdouble ysize;
+ gint perm_tab[TABLE_SIZE];
+ Vector2 grad_tab[TABLE_SIZE];
+} NsParamsType;
+
+static void
+solid_noise_init (GeglProperties *o)
+{
+ gint i, j, k, t;
+ gdouble m;
+ GRand *gr;
+ NsParamsType *params;
+
+ params = (NsParamsType *) o->user_data;
+
+ g_assert (params != NULL);
+
+ gr = g_rand_new_with_seed (o->seed);
+
+ /* Set scaling factors */
+ if (o->tilable)
+ {
+ params->xsize = ceil (o->x_size);
+ params->ysize = ceil (o->y_size);
+ params->xclip = (gint) params->xsize;
+ params->yclip = (gint) params->ysize;
+ }
+ else
+ {
+ params->xsize = o->x_size;
+ params->ysize = o->y_size;
+ }
+
+ /* Set totally empiric normalization values */
+ if (o->turbulent)
+ {
+ params->offset = 0.0;
+ params->factor = 1.0;
+ }
+ else
+ {
+ params->offset = 0.94;
+ params->factor = 0.526;
+ }
+
+ /* Initialize the permutation table */
+ for (i = 0; i < TABLE_SIZE; i++)
+ params->perm_tab[i] = i;
+
+ for (i = 0; i < (TABLE_SIZE >> 1); i++)
+ {
+ j = g_rand_int_range (gr, 0, TABLE_SIZE);
+ k = g_rand_int_range (gr, 0, TABLE_SIZE);
+ t = params->perm_tab[j];
+ params->perm_tab[j] = params->perm_tab[k];
+ params->perm_tab[k] = t;
+ }
+
+ /* Initialize the gradient table */
+ for (i = 0; i < TABLE_SIZE; i++)
+ {
+ do
+ {
+ params->grad_tab[i].x = g_rand_double_range (gr, -1, 1);
+ params->grad_tab[i].y = g_rand_double_range (gr, -1, 1);
+ m = params->grad_tab[i].x * params->grad_tab[i].x +
+ params->grad_tab[i].y * params->grad_tab[i].y;
+ }
+ while (m == 0.0 || m > 1.0);
+
+ m = 1.0 / sqrt(m);
+ params->grad_tab[i].x *= m;
+ params->grad_tab[i].y *= m;
+ }
+
+ g_rand_free (gr);
+}
+
+static gdouble
+plain_noise (gdouble x,
+ gdouble y,
+ guint s,
+ GeglProperties *o)
+{
+ Vector2 v;
+ gint a, b, i, j, n;
+ gdouble sum;
+ NsParamsType *p;
+
+ p = (NsParamsType *) o->user_data;
+
+ sum = 0.0;
+ x *= s;
+ y *= s;
+ a = (gint) floor (x);
+ b = (gint) floor (y);
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ if (o->tilable)
+ n = p->perm_tab[(((a + i) % (p->xclip * s)) + p->perm_tab[((b + j) % (p->yclip * s)) %
TABLE_SIZE]) % TABLE_SIZE];
+ else
+ n = p->perm_tab[(a + i + p->perm_tab[(b + j) % TABLE_SIZE]) % TABLE_SIZE];
+ v.x = x - a - i;
+ v.y = y - b - j;
+ sum += WEIGHT(v.x) * WEIGHT(v.y) * (p->grad_tab[n].x * v.x + p->grad_tab[n].y * v.y);
+ }
+ }
+
+ return sum / s;
+}
+
+static gdouble
+noise (gdouble x,
+ gdouble y,
+ GeglProperties *o)
+{
+ gint i;
+ guint s;
+ gdouble sum;
+ NsParamsType *p;
+
+ p = (NsParamsType *) o->user_data;
+
+ s = 1;
+ sum = 0.0;
+ x *= p->xsize;
+ y *= p->ysize;
+
+ for (i = 0; i <= o->detail; i++)
+ {
+ if (o->turbulent)
+ sum += fabs (plain_noise (x, y, s, o));
+ else
+ sum += plain_noise (x, y, s, o);
+ s <<= 1;
+ }
+
+ return (sum + p->offset) * p->factor;
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *format = babl_format ("Y' float");
+
+ if (o->user_data == NULL)
+ o->user_data = g_slice_new0 (NsParamsType);
+
+ solid_noise_init (o);
+
+ gegl_operation_set_format (operation, "output", format);
+}
+
+static gboolean
+c_process (GeglOperation *operation,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ gint x, y;
+ gfloat val;
+ gfloat *output = out_buf;
+
+ for (y = roi->y; y < (roi->y + roi->height); y++)
+ {
+ for (x = roi->x; x < (roi->x + roi->width); x++)
+ {
+ val = noise (((gdouble) x / o->width), ((gdouble) y / o->height), o);
+ *output = val;
+ output++;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *out_buf,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglBufferIterator *iter;
+ const Babl *format = gegl_operation_get_format (operation,
+ "output");
+
+ iter = gegl_buffer_iterator_new (out_buf, roi, level, format,
+ GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
+
+ while (gegl_buffer_iterator_next (iter))
+ c_process (operation, iter->data[0], iter->length, &iter->roi[0], level);
+
+ return TRUE;
+}
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+ return gegl_rectangle_infinite_plane ();
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationSourceClass *source_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ source_class = GEGL_OPERATION_SOURCE_CLASS (klass);
+
+ source_class->process = process;
+ operation_class->get_bounding_box = get_bounding_box;
+ operation_class->prepare = prepare;
+ operation_class->opencl_support = FALSE;
+
+ gegl_operation_class_set_keys (operation_class,
+ "name", "gegl:noise-solid",
+ "title", _("Solid Noise"),
+ "categories", "render",
+ "position-dependent", "true",
+ "license", "GPL3+",
+ "description", _("Create a random cloud-like texture"),
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f6ef74b..5f55a2d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -78,6 +78,7 @@ operations/common/noise-reduction.c
operations/common/noise-simplex.c
operations/common/noise-rgb.c
operations/common/noise-slur.c
+operations/common/noise-solid.c
operations/common/noise-spread.c
operations/common/oilify.c
operations/common/opacity.c
diff --git a/tests/compositions/Makefile.am b/tests/compositions/Makefile.am
index ea83747..adb5e99 100644
--- a/tests/compositions/Makefile.am
+++ b/tests/compositions/Makefile.am
@@ -36,6 +36,7 @@ TESTS = \
noise-cell.xml \
noise-hurl.xml \
noise-simplex.xml \
+ noise-solid.xml \
pixelize.xml \
posterize.xml \
red-eye-removal.xml \
diff --git a/tests/compositions/noise-solid.xml b/tests/compositions/noise-solid.xml
new file mode 100644
index 0000000..ca55faf
--- /dev/null
+++ b/tests/compositions/noise-solid.xml
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gegl>
+ <node operation='gegl:crop'>
+ <params>
+ <param name='x'>0</param>
+ <param name='y'>0</param>
+ <param name='width'>400</param>
+ <param name='height'>400</param>
+ </params>
+ </node>
+ <node operation='gegl:noise-solid'>
+ <params>
+ <param name='x-size'>5.00</param>
+ <param name='y-size'>5.00</param>
+ <param name='detail'>10</param>
+ <param name='tilable'>true</param>
+ <param name='turbulent'>true</param>
+ <param name='seed'>0</param>
+ <param name="width">100</param>
+ <param name="height">100</param>
+ </params>
+ </node>
+</gegl>
diff --git a/tests/compositions/reference/noise-solid.png b/tests/compositions/reference/noise-solid.png
new file mode 100644
index 0000000..ec029ff
Binary files /dev/null and b/tests/compositions/reference/noise-solid.png differ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]