[gegl] workshop: add spiral operation
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] workshop: add spiral operation
- Date: Tue, 18 Apr 2017 00:43:44 +0000 (UTC)
commit 95573de6103ea0a7126260d3fa6fc4f7c5a18dd8
Author: Ell <ell_se yahoo com>
Date: Mon Apr 17 20:14:56 2017 -0400
workshop: add spiral operation
It, er, renders a spiral. You're feeling dizzy...
operations/workshop/Makefile.am | 3 +-
operations/workshop/spiral.c | 245 +++++++++++++++++++++++++++++++++++++++
po/POTFILES.in | 1 +
3 files changed, 248 insertions(+), 1 deletions(-)
---
diff --git a/operations/workshop/Makefile.am b/operations/workshop/Makefile.am
index e190b1d..008412d 100644
--- a/operations/workshop/Makefile.am
+++ b/operations/workshop/Makefile.am
@@ -27,4 +27,5 @@ op_LTLIBRARIES = \
rawbayer-load.la \
segment-kmeans.la \
shadows-highlights.la \
- shadows-highlights-correction.la
+ shadows-highlights-correction.la \
+ spiral.la
diff --git a/operations/workshop/spiral.c b/operations/workshop/spiral.c
new file mode 100644
index 0000000..1d5bbe1
--- /dev/null
+++ b/operations/workshop/spiral.c
@@ -0,0 +1,245 @@
+/* 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/>.
+ *
+ * Copyright (C) 2017 Ell
+ *
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <math.h>
+
+#ifdef GEGL_PROPERTIES
+
+property_double (x, _("X"), 0.5)
+ description (_("Spiral origin X coordinate"))
+ ui_range (0.0, 1.0)
+ ui_meta ("unit", "relative-coordinate")
+ ui_meta ("axis", "x")
+
+property_double (y, _("Y"), 0.5)
+ description (_("Spiral origin Y coordinate"))
+ ui_range (0.0, 1.0)
+ ui_meta ("unit", "relative-coordinate")
+ ui_meta ("axis", "y")
+
+property_double (radius, _("Radius"), 100.0)
+ description (_("Spiral radius"))
+ value_range (1.0, G_MAXDOUBLE)
+ ui_range (1.0, 400.0)
+ ui_meta ("unit", "pixel-distance")
+
+property_double (thickness, _("Thickness"), 0.5)
+ description (_("Spiral thickness, as a fraction of the radius"))
+ value_range (0.0, 1.0)
+
+property_double (angle, _("Angle"), 0.0)
+ description (_("Spiral start angle"))
+ value_range (0.0, 360.0)
+ ui_meta ("unit", "degree")
+
+property_boolean (clockwise, _("Clockwise"), TRUE)
+ description (_("Expand spiral clockwise"))
+
+property_color (color1, _("Color 1"), "black")
+ ui_meta ("role", "color-primary")
+
+property_color (color2, _("Color 2"), "white")
+ ui_meta ("role", "color-secondary")
+
+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_NAME spiral
+#define GEGL_OP_C_SOURCE spiral.c
+
+#include "gegl-op.h"
+#include <math.h>
+
+static inline gdouble
+odd_pow (gdouble base,
+ gdouble exponent)
+{
+ if (base >= 0.0)
+ return pow ( base, exponent);
+ else
+ return -pow (-base, exponent);
+}
+
+static void
+prepare (GeglOperation *operation)
+{
+ 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 inline void
+blend (const gfloat *color1,
+ const gfloat *color2,
+ gfloat a,
+ gfloat *result)
+{
+ if (a == 0.0)
+ {
+ memcpy (result, color1, 4 * sizeof (gfloat));
+ }
+ else if (a == 1.0)
+ {
+ memcpy (result, color2, 4 * sizeof (gfloat));
+ }
+ else
+ {
+ gfloat alpha = color1[3] + a * (color2[3] - color1[3]);
+ gint c;
+
+ if (alpha)
+ {
+ gfloat ratio = a * color2[3] / alpha;
+
+ for (c = 0; c < 3; c++)
+ result[c] = color1[c] + ratio * (color2[c] - color1[c]);
+ }
+ else
+ {
+ memcpy (result, color1, 3 * sizeof (gfloat));
+ }
+
+ result[3] = alpha;
+ }
+}
+
+static gboolean
+process (GeglOperation *operation,
+ void *out_buf,
+ glong n_pixels,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglProperties *o = GEGL_PROPERTIES (operation);
+ const Babl *format = babl_format ("R'G'B'A float");
+ gfloat *dest = out_buf;
+ gdouble radius = o->radius;
+ gdouble lim = radius * o->thickness;
+ gdouble angle = G_PI * o->angle / 180.0;
+ gboolean clockwise = o->clockwise;
+ gfloat color1[4];
+ gfloat color2[4];
+ gdouble x0;
+ gdouble x;
+ gdouble y;
+ gint i;
+ gint j;
+
+ gegl_color_get_pixel (o->color1, format, color1);
+ gegl_color_get_pixel (o->color2, format, color2);
+
+ if (radius == 1.0 || o->thickness == 0.0 || o->thickness == 1.0)
+ {
+ gfloat color[4];
+
+ blend (color2, color1, o->thickness, color);
+
+ gegl_memset_pattern (dest, color, sizeof (color), n_pixels);
+
+ return TRUE;
+ }
+
+ if (clockwise)
+ angle = G_PI - angle;
+
+ angle += 2 * G_PI;
+
+ x0 = roi->x - gegl_coordinate_relative_to_pixel (o->x, o->width);
+ y = roi->y - gegl_coordinate_relative_to_pixel (o->y, o->height);
+
+ for (j = roi->height; j; j--, y++)
+ {
+ gdouble y2 = y * y;
+
+ x = x0;
+
+ for (i = roi->width; i; i--, x++)
+ {
+ gdouble x2 = x * x;
+ gdouble r = sqrt (x2 + y2);
+ gdouble t = atan2 (y, clockwise ? -x : x) + angle;
+ gdouble a;
+ gdouble l;
+
+ l = fmod (r + radius * t / (2.0 * G_PI), radius);
+
+ if (l < 0.5)
+ a = MIN (lim, l + 0.5) + MAX (lim - (radius + l - 0.5), 0.0);
+ else if (l > radius - 0.5)
+ a = MAX (lim - l + 0.5, 0.0) + MIN (lim, l + 0.5 - radius);
+ else
+ a = CLAMP (lim - l + 0.5, 0.0, 1.0);
+
+ blend (color2, color1, a, dest);
+
+ dest += 4;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationPointRenderClass *point_render_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ point_render_class = GEGL_OPERATION_POINT_RENDER_CLASS (klass);
+
+ 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:spiral",
+ "title", _("Spiral"),
+ "categories", "render",
+ "position-dependent", "true",
+ "license", "GPL3+",
+ "description", _("Spiral renderer"),
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index fae2756..6604981 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -252,3 +252,4 @@ operations/workshop/rawbayer-load.c
operations/workshop/segment-kmeans.c
operations/workshop/shadows-highlights.c
operations/workshop/shadows-highlights-correction.c
+operations/workshop/spiral.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]