[gegl] Bug 740454 - Port the gimp Sinus plug-in as gegl:sinus
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Bug 740454 - Port the gimp Sinus plug-in as gegl:sinus
- Date: Fri, 21 Nov 2014 19:42:37 +0000 (UTC)
commit fb56c9726d8b3cf07072dc4c5578bc5fda47014a
Author: Thomas Manni <thomas manni free fr>
Date: Thu Nov 20 20:28:39 2014 +0100
Bug 740454 - Port the gimp Sinus plug-in as gegl:sinus
operations/common/Makefile.am | 1 +
operations/common/sinus.c | 321 ++++++++++++++++++++++++++++++++
po/POTFILES.in | 1 +
tests/compositions/Makefile.am | 1 +
tests/compositions/reference/sinus.png | Bin 0 -> 282974 bytes
tests/compositions/sinus.xml | 25 +++
6 files changed, 349 insertions(+), 0 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index 502c7f2..e49b7f1 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -104,6 +104,7 @@ op_LTLIBRARIES = \
ripple.la \
save.la \
shift.la \
+ sinus.la \
snn-mean.la \
softglow.la \
stress.la \
diff --git a/operations/common/sinus.c b/operations/common/sinus.c
new file mode 100644
index 0000000..fd09731
--- /dev/null
+++ b/operations/common/sinus.c
@@ -0,0 +1,321 @@
+/* This file is an image processing operation for GEGL
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Exchange one color with the other (settable threshold to convert from
+ * one color-shade to another...might do wonders on certain images, or be
+ * totally useless on others).
+ *
+ * Copyright (C) 1997 Xavier Bouchoux
+ *
+ * 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_scale, _("X Scale"), 15.0000)
+ description (_("Scale value for x axis"))
+ value_range (0.0001, G_MAXDOUBLE)
+ ui_range (0.0001, 100.0000)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "x")
+
+property_double (y_scale, _("Y Scale"), 15.0)
+ description (_("Scale value for y axis"))
+ value_range (0.0001, G_MAXDOUBLE)
+ ui_range (0.0001, 100.0000)
+ ui_meta ("unit", "pixel-distance")
+ ui_meta ("axis", "y")
+
+property_double (complexity, _("Complexity"), 1.0)
+ description (_("Complexity factor"))
+ value_range (0.0, 15.0)
+
+property_seed (seed, _("Random seed"), rand)
+
+property_boolean (tiling, _("Force tiling"), TRUE)
+ description (_("If set, the pattern generated will tile"))
+
+property_boolean (perturbation, _("Distorted"), TRUE)
+ description (_("If set, the pattern will be a little more distorted"))
+
+property_color (color1, _("Color 1"), "yellow")
+
+property_color (color2, _("Color 2"), "blue")
+
+enum_start (gegl_sinus_blend)
+ enum_value (GEGL_SINUS_BLEND_LINEAR , "linear", N_("Linear"))
+ enum_value (GEGL_SINUS_BLEND_BILINEAR , "bilinear", N_("Bilinear"))
+ enum_value (GEGL_SINUS_BLEND_SINUSOIDAL, "sinusoidal", N_("Sinusoidal"))
+enum_end (GeglSinusBlend)
+
+property_enum (blend_mode, _("Blend Mode"),
+ GeglSinusBlend, gegl_sinus_blend,
+ GEGL_SINUS_BLEND_SINUSOIDAL)
+
+property_double (blend_power, _("Exponent"), 0.0)
+ description (_("Power used to strech the blend"))
+ value_range (-7.5, 7.5)
+
+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 "sinus.c"
+
+#include "gegl-op.h"
+
+#define ROUND(x) ((int) ((x) + 0.5))
+
+typedef struct
+{
+ gdouble c11, c12, c13, c21, c22, c23, c31, c32, c33;
+ gdouble (*blend) (gdouble);
+ gfloat color[4];
+ gfloat dcolor[4];
+} SParamsType;
+
+static gdouble
+linear (gdouble v)
+{
+ gdouble a = v - (gint) v;
+
+ return (a < 0 ? 1.0 + a : a);
+}
+
+static gdouble
+bilinear (gdouble v)
+{
+ double a = v - (int) v;
+
+ a = (a < 0 ? 1.0 + a : a);
+ return (a > 0.5 ? 2 - 2 * a : 2 * a);
+}
+
+static gdouble
+cosinus (gdouble v)
+{
+ return 0.5 - 0.5 * sin ((v + 0.25) * G_PI * 2);
+}
+
+static void
+prepare_coef (GeglProperties *o)
+{
+ SParamsType *params;
+ GRand *gr;
+ gfloat color[4];
+ gdouble scalex = o->x_scale;
+ gdouble scaley = o->y_scale;
+
+ params = (SParamsType *) o->user_data;
+
+ gr = g_rand_new_with_seed (o->seed);
+
+ switch (o->blend_mode)
+ {
+ case GEGL_SINUS_BLEND_BILINEAR:
+ params->blend = bilinear;
+ break;
+ case GEGL_SINUS_BLEND_SINUSOIDAL:
+ params->blend = cosinus;
+ break;
+ case GEGL_SINUS_BLEND_LINEAR:
+ default:
+ params->blend = linear;
+ }
+
+ if (! o->perturbation)
+ {
+ /* Presumably the 0 * g_rand_int ()s are to pop random
+ * values off the prng, I don't see why though. */
+ params->c11= 0 * g_rand_int (gr);
+ params->c12= g_rand_double_range (gr, -1, 1) * scaley;
+ params->c13= g_rand_double_range (gr, 0, 2 * G_PI);
+ params->c21= 0 * g_rand_int (gr);
+ params->c22= g_rand_double_range (gr, -1, 1) * scaley;
+ params->c23= g_rand_double_range (gr, 0, 2 * G_PI);
+ params->c31= g_rand_double_range (gr, -1, 1) * scalex;
+ params->c32= 0 * g_rand_int (gr);
+ params->c33= g_rand_double_range (gr, 0, 2 * G_PI);
+ }
+ else
+ {
+ params->c11= g_rand_double_range (gr, -1, 1) * scalex;
+ params->c12= g_rand_double_range (gr, -1, 1) * scaley;
+ params->c13= g_rand_double_range (gr, 0, 2 * G_PI);
+ params->c21= g_rand_double_range (gr, -1, 1) * scalex;
+ params->c22= g_rand_double_range (gr, -1, 1) * scaley;
+ params->c23= g_rand_double_range (gr, 0, 2 * G_PI);
+ params->c31= g_rand_double_range (gr, -1, 1) * scalex;
+ params->c32= g_rand_double_range (gr, -1, 1) * scaley;
+ params->c33= g_rand_double_range (gr, 0, 2 * G_PI);
+ }
+
+ if (o->tiling)
+ {
+ params->c11 = ROUND (params->c11 / (2 * G_PI)) * 2 * G_PI;
+ params->c12 = ROUND (params->c12 / (2 * G_PI)) * 2 * G_PI;
+ params->c21 = ROUND (params->c21 / (2 * G_PI)) * 2 * G_PI;
+ params->c22 = ROUND (params->c22 / (2 * G_PI)) * 2 * G_PI;
+ params->c31 = ROUND (params->c31 / (2 * G_PI)) * 2 * G_PI;
+ params->c32 = ROUND (params->c32 / (2 * G_PI)) * 2 * G_PI;
+ }
+
+ gegl_color_get_pixel (o->color1, babl_format ("R'G'B'A float"),
+ &(params->color));
+
+ gegl_color_get_pixel (o->color2, babl_format ("R'G'B'A float"),
+ &color);
+
+ params->dcolor[0] = color[0] - params->color[0];
+ params->dcolor[1] = color[1] - params->color[1];
+ params->dcolor[2] = color[2] - params->color[2];
+ params->dcolor[3] = color[3] - params->color[3];
+
+ g_rand_free (gr);
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+
+ if (o->user_data == NULL)
+ o->user_data = g_slice_new0 (SParamsType);
+
+ prepare_coef (o);
+
+ gegl_operation_set_format (operation, "output", babl_format ("R'G'B'A float"));
+}
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+ return gegl_rectangle_infinite_plane ();
+}
+
+static gboolean
+process (GeglOperation *operation,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ SParamsType *p;
+ gint i, j;
+ gdouble x, y, grey;
+ gdouble pow_exp;
+ gfloat *dest = out_buf;
+
+ p = (SParamsType *) o->user_data;
+
+ pow_exp = exp (o->blend_power);
+
+ for (j = roi->y; j < roi->y + roi->height; j++)
+ {
+ y = ((gdouble) j) / o->height;
+ for (i = roi->x; i < roi->x + roi->width; i++)
+ {
+ gdouble c;
+
+ x = ((gdouble) i) / o->width;
+
+ c = 0.5 * sin(p->c31 * x + p->c32 * y + p->c33);
+
+ grey = sin (p->c11 * x + p->c12 * y + p->c13) *
+ (0.5 + 0.5 * c) +
+ sin (p->c21 * x + p->c22 * y + p->c23) *
+ (0.5 - 0.5 * c);
+
+ grey = pow (p->blend (o->complexity * (0.5 + 0.5 * grey)), pow_exp);
+
+ dest[0] = p->color[0] + grey * p->dcolor[0];
+ dest[1] = p->color[1] + grey * p->dcolor[1];
+ dest[2] = p->color[2] + grey * p->dcolor[2];
+ dest[3] = p->color[3] + grey * p->dcolor[3];
+
+ dest += 4;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+finalize (GObject *object)
+{
+ GeglOperation *op = (void*) object;
+ GeglProperties *o = GEGL_PROPERTIES (op);
+
+ if (o->user_data)
+ {
+ g_slice_free (SParamsType, o->user_data);
+ o->user_data = NULL;
+ }
+
+ G_OBJECT_CLASS (gegl_op_parent_class)->finalize (object);
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GObjectClass *object_class;
+ GeglOperationClass *operation_class;
+ GeglOperationPointRenderClass *point_render_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ point_render_class = GEGL_OPERATION_POINT_RENDER_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ point_render_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:sinus",
+ "title", _("Sinus"),
+ "categories", "render",
+ "position-dependent", "true",
+ "license", "GPL3+",
+ "description", _("Generate complex sinusoidal textures"),
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index ca95ea1..f6ef74b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -98,6 +98,7 @@ operations/common/remap.c
operations/common/ripple.c
operations/common/save.c
operations/common/shift.c
+operations/common/sinus.c
operations/common/snn-mean.c
operations/common/softglow.c
operations/common/stress.c
diff --git a/tests/compositions/Makefile.am b/tests/compositions/Makefile.am
index 2f04d17..ea83747 100644
--- a/tests/compositions/Makefile.am
+++ b/tests/compositions/Makefile.am
@@ -45,6 +45,7 @@ TESTS = \
rgb-params.xml \
rotate.xml \
simple-scale.xml \
+ sinus.xml \
softglow.xml \
stretch-contrast.xml \
supernova.xml \
diff --git a/tests/compositions/reference/sinus.png b/tests/compositions/reference/sinus.png
new file mode 100644
index 0000000..60143b0
Binary files /dev/null and b/tests/compositions/reference/sinus.png differ
diff --git a/tests/compositions/sinus.xml b/tests/compositions/sinus.xml
new file mode 100644
index 0000000..14bd47f
--- /dev/null
+++ b/tests/compositions/sinus.xml
@@ -0,0 +1,25 @@
+<?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:sinus'>
+ <params>
+ <param name='x-scale'>12.00</param>
+ <param name='y-scale'>12.00</param>
+ <param name='complexity'>10.000</param>
+ <param name='seed'>0</param>
+ <param name='tiling'>true</param>
+ <param name='perturbation'>true</param>
+ <param name="blend-mode">sinusoidal</param>
+ <param name="blend-power">-1.000</param>
+ <param name="width">100</param>
+ <param name="height">100</param>
+ </params>
+ </node>
+</gegl>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]