[gegl] plasma: Add the plasma op from soc-2011-ops branch
- From: Mukund Sivaraman <muks src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] plasma: Add the plasma op from soc-2011-ops branch
- Date: Thu, 30 Jun 2011 09:42:40 +0000 (UTC)
commit 154f01f63fc68d548cfa35e826b3286733639f5d
Author: Robert Sasu <sasu robert gmail com>
Date: Thu Jun 30 14:16:42 2011 +0530
plasma: Add the plasma op from soc-2011-ops branch
operations/workshop/plasma.c | 338 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 338 insertions(+), 0 deletions(-)
---
diff --git a/operations/workshop/plasma.c b/operations/workshop/plasma.c
new file mode 100644
index 0000000..a476fc6
--- /dev/null
+++ b/operations/workshop/plasma.c
@@ -0,0 +1,338 @@
+/* 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/>.
+ *
+ * Algorithm 1996 Stephen Norris
+ * Copyright 2011 Robert Sasu (sasu robert gmail com)
+ */
+
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_int (seed, _("Seed"), 0 , G_MAXINT, 1,
+ _("Random seed"))
+gegl_chant_double (turbulance, _("Turbulance"), 0.1, 7.0, 2,
+ _("The value of the turbulance"))
+
+#else
+
+#define GEGL_CHANT_TYPE_FILTER
+
+#define GEGL_CHANT_C_FILE "plasma.c"
+#define floats_per_pixel 4
+#define MANUAL_ROI_VAL 500
+
+
+#include "gegl-chant.h"
+#include <math.h>
+#include <stdio.h>
+
+static void prepare (GeglOperation *operation)
+{
+ gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
+ gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+}
+
+static void
+average_pixel (gfloat *dst_buf,
+ gfloat *src_buf1,
+ gfloat *src_buf2)
+{
+ gint i;
+ for (i = 0; i < floats_per_pixel; i++)
+ *dst_buf++ = (*src_buf1++ + *src_buf2++) / 2;
+}
+
+static void
+random_rgba (GRand *gr,
+ gfloat *dest)
+{
+ gint i;
+ for (i = 0; i < floats_per_pixel - 1; i++)
+ dest[i] = (gfloat) g_rand_double_range (gr, 0, 1);
+
+ dest[i] = 1;
+}
+
+static void
+add_random (GRand *gr,
+ gfloat *dest,
+ gfloat amount)
+{
+ gint i;
+ gfloat tmp;
+ gdouble rnd;
+
+
+ amount /= 2;
+ rnd = fabs(fmod(amount, 1));
+
+ if (amount > 0)
+ for (i = 0; i < floats_per_pixel-1; i++)
+ {
+ tmp = dest[i] + (gfloat) g_rand_double_range(gr, -rnd, rnd);
+ dest[i] = CLAMP (tmp, 0, 1);
+ }
+}
+
+static void
+put_pixel_to_buffer (GeglBuffer *output,
+ gfloat *pixel,
+ gint x,
+ gint y)
+{
+ GeglRectangle rect = {1, 1, 1, 1};
+ rect.x = x;
+ rect.y = y;
+ gegl_buffer_set (output, &rect, babl_format ("RGBA float"), pixel,
+ GEGL_AUTO_ROWSTRIDE);
+}
+
+static gboolean
+do_plasma_big (GeglBuffer *output,
+ gint x1,
+ gint y1,
+ gint x2,
+ gint y2,
+ gint depth,
+ gint scale_depth,
+ GRand *gr,
+ GeglChantO *op)
+{
+ gfloat *tl, *ml, *bl, *mt, *mm, *mb, *tr, *mr, *br;
+ gfloat *tmp;
+ gint xm, ym;
+ gfloat ran;
+ static gint count = 0;
+ /*
+ GeglRectangle roi = {0, 0, 0, 0};
+ gfloat *src_buf;
+ gboolean toreturn;
+ */
+ tl = ml = bl = mt = mm = mb = tr = mr = br = tmp
+ = g_new0 (gfloat, floats_per_pixel);
+
+ xm = (x1 + x2) / 2;
+ ym = (y1 + y2) / 2;
+
+ if (depth == -1)
+ {
+ random_rgba (gr, tl);
+ put_pixel_to_buffer (output, tl, x1, y1);
+
+ random_rgba (gr, tr);
+ put_pixel_to_buffer (output, tr, x2, y1);
+
+ random_rgba (gr, bl);
+ put_pixel_to_buffer (output, bl, x1, y2);
+
+ random_rgba (gr, br);
+ put_pixel_to_buffer (output, br, x2, y2);
+
+ random_rgba (gr, mm);
+ put_pixel_to_buffer (output, mm, xm, ym);
+
+ random_rgba (gr, ml);
+ put_pixel_to_buffer (output, ml, x1, ym);
+
+ random_rgba (gr, mr);
+ put_pixel_to_buffer (output, mr, x2, ym);
+
+ random_rgba (gr, mt);
+ put_pixel_to_buffer (output, mt, xm, y1);
+
+ random_rgba (gr, mb);
+ put_pixel_to_buffer (output, mb, xm, y2);
+ /*ugly but working*/
+ return FALSE;
+ }
+
+ if (!depth)
+ {
+ if (x1 == x2 && y1 == y2) return FALSE;
+
+ gegl_buffer_sample (output, x1, y1, 1.0, tl, babl_format ("RGBA float"),
+ GEGL_INTERPOLATION_LINEAR);
+ gegl_buffer_sample (output, x1, y2, 1.0, bl, babl_format ("RGBA float"),
+ GEGL_INTERPOLATION_LINEAR);
+ gegl_buffer_sample (output, x2, y1, 1.0, tr, babl_format ("RGBA float"),
+ GEGL_INTERPOLATION_LINEAR);
+ gegl_buffer_sample (output, x2, y2, 1.0, br, babl_format ("RGBA float"),
+ GEGL_INTERPOLATION_LINEAR);
+
+ ran = ((gfloat) op->turbulance / (2.0 * scale_depth));
+
+ if (xm != x1 || xm != x2)
+ {
+ /*left*/
+ average_pixel (ml, tl, bl);
+ add_random (gr, ml, ran);
+ put_pixel_to_buffer (output, ml, x1, ym);
+
+ /*right*/
+ if (x1 != x2)
+ {
+ average_pixel (mr, tr, br);
+ add_random (gr, mr, ran);
+ put_pixel_to_buffer (output, mr, x2, ym);
+ }
+ }
+
+
+ if (ym != y1 || ym != x2)
+ {
+ /*bottom*/
+ if (x1 != xm || ym != y2)
+ {
+ average_pixel (mb, bl, br);
+ add_random (gr, mb, ran);
+ put_pixel_to_buffer (output, mb, xm, y2);
+ }
+
+ if (y1 != y2)
+ {
+ /*top*/
+ average_pixel (mt, tl, tr);
+ add_random (gr, mt, ran);
+ put_pixel_to_buffer (output, mt, xm, y1);
+ }
+ }
+
+ if (y1 != y2 || x1 != x2)
+ {
+ average_pixel (mm, tl, br);
+ average_pixel (tmp, bl, tr);
+ average_pixel (mm, mm, tmp);
+
+ add_random (gr, mm, ran);
+ put_pixel_to_buffer (output, mm, xm, ym);
+ }
+ count++;
+
+ return x2 - x1 < 3 && y2 - y1 < 3;
+ }
+
+ if (x1 < x2 || y1 < y2)
+ {
+ /*top-left*/
+ do_plasma_big (output, x1, y1, xm, ym, depth - 1,
+ scale_depth + 1, gr, op);
+ /*bottom-left*/
+ do_plasma_big (output, x1, ym, xm, y2, depth - 1,
+ scale_depth + 1, gr, op);
+ /*top-right*/
+ do_plasma_big (output, xm, y1, x2, ym, depth - 1,
+ scale_depth + 1, gr, op);
+ /*bottom-right*/
+ return do_plasma_big (output, xm, ym, x2, y2, depth - 1,
+ scale_depth + 1, gr, op);
+ }
+ else return TRUE;
+
+ return TRUE;
+}
+
+
+
+static GeglRectangle
+plasma_get_bounding_box (GeglOperation *operation)
+{
+ GeglRectangle result = {0,0,0,0};
+ GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input");
+
+ gegl_rectangle_copy (&result, in_rect);
+
+ return result;
+}
+
+
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+
+ GeglRectangle boundary=plasma_get_bounding_box(operation);
+
+ GRand *gr = g_rand_new_with_seed (o->seed);
+ gint depth;
+ gint x, y;
+
+ /*
+ * The first time only puts seed pixels (corners, center of edges,
+ * center of image)
+ */
+ x = boundary.x + boundary.width;
+ y = boundary.y + boundary.height;
+
+ do_plasma_big (output, boundary.x, boundary.y, x-1, y-1, -1,
+ 0, gr, o);
+ /*
+ * Now we recurse through the images, going deeper each time
+ */
+ depth = 1;
+ while (!do_plasma_big (output, boundary.x, boundary.y, x-1,
+ y-1, depth, 0, gr, o))
+
+ depth++;
+
+ return TRUE;
+}
+
+static GeglRectangle
+get_required_for_output (GeglOperation *operation,
+ const gchar *input_pad,
+ const GeglRectangle *roi)
+{
+ GeglRectangle result = *gegl_operation_source_get_bounding_box (operation,
+ "input");
+ return result;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation *operation,
+ const GeglRectangle *roi)
+{
+ return *gegl_operation_source_get_bounding_box (operation, "input");
+}
+
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationFilterClass *filter_class;
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
+
+ filter_class->process = process;
+ operation_class->prepare = prepare;
+ operation_class->get_required_for_output = get_required_for_output;
+ operation_class->get_cached_region = get_cached_region;
+
+ operation_class->categories = "render";
+ operation_class->name = "gegl:plasma";
+ operation_class->description =
+ _("Performs plasma on the image.");
+}
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]