[gegl/soc-2011-ops] Added the plasma op (with bugs)
- From: Robert Sasu <sasurobert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2011-ops] Added the plasma op (with bugs)
- Date: Mon, 20 Jun 2011 18:39:36 +0000 (UTC)
commit 990d21bb87feb46229b99a786529fc0a2062fb0e
Author: Robert Sasu <sasu robert gmail com>
Date: Mon Jun 20 21:39:00 2011 +0300
Added the plasma op (with bugs)
operations/workshop/plasma.c | 346 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 346 insertions(+), 0 deletions(-)
---
diff --git a/operations/workshop/plasma.c b/operations/workshop/plasma.c
new file mode 100644
index 0000000..919d2b4
--- /dev/null
+++ b/operations/workshop/plasma.c
@@ -0,0 +1,346 @@
+/* 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 , 10, 1,
+ _("Random seed"))
+gegl_chant_double (turbulance, _("Turbulance"), 0.1, 7.0, 2,
+ _("The value of the turbulance"))
+
+#else
+
+#define GEGL_CHANT_TYPE_AREA_FILTER
+
+#define GEGL_CHANT_C_FILE "plasma.c"
+#define RADIUS 5
+#define floats_per_pixel 4
+
+#include "gegl-chant.h"
+#include <math.h>
+#include <stdio.h>
+
+FILE *f;
+
+static void prepare (GeglOperation *operation)
+{
+ GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
+
+ op_area->left = op_area->right = op_area->top = op_area->bottom = RADIUS;
+
+ 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;
+
+ amount /= 2;
+ amount = fmod(amount, 1);
+// fprintf(f,"%lf \n",amount);
+ if (amount > 0)
+ for (i = 0; i < floats_per_pixel-1; i++)
+ {
+ tmp = dest[i] + (gfloat) g_rand_double_range (gr, -amount, amount);
+ dest[i] = CLAMP (tmp, 0, 1);
+ }
+}
+
+static void
+put_pixel (gfloat *dst_buf,
+ gfloat *pixel,
+ gint offset)
+{
+ gint i;
+ for (i = 0; i < floats_per_pixel; i++)
+ dst_buf[offset++] = pixel[i];
+}
+
+
+static void
+get_pixel (gfloat *src_buf,
+ const GeglRectangle *src,
+ gint x,
+ gint y,
+ gfloat *dst)
+{
+ gint i, offset;
+ offset = ((y - src->y) * src->width + x - src->x) * floats_per_pixel;
+ // fprintf(f,"%d\n",offset);
+ for (i = 0; i < floats_per_pixel; i++)
+ dst[i] = src_buf[offset++];
+
+ dst[i] = dst[i];
+}
+
+
+static gboolean
+do_plasma (gfloat *src_buf,
+ const GeglRectangle *src,
+ gfloat *dst_buf,
+ const GeglRectangle *dst,
+ 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;
+ gint offset;
+ static gint count = 0;
+
+ 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);
+ offset = ((y1 - dst->y) * dst->width + x1 - dst->x) * 4;
+ put_pixel (dst_buf, tl, offset);
+ random_rgba (gr, tr);
+ offset = ((y1 - dst->y) * dst->width + x2 - dst->x) * 4;
+ put_pixel (dst_buf, tr, offset);
+ random_rgba (gr, bl);
+ offset = ((y2 - dst->y) * dst->width + x1 - dst->x) * 4;
+ put_pixel (dst_buf, bl, offset);
+ random_rgba (gr, br);
+ offset = ((y2 - dst->y) * dst->width + x2 - dst->x) * 4;
+ put_pixel (dst_buf, br, offset);
+ random_rgba (gr, mm);
+ offset = ((ym - dst->y) * dst->width + xm - dst->x) * 4;
+ put_pixel (dst_buf, mm, offset);
+ random_rgba (gr, ml);
+ offset = ((ym - dst->y) * dst->width + x1 - dst->x) * 4;
+ put_pixel (dst_buf, ml, offset);
+ random_rgba (gr, mr);
+ offset = ((ym - dst->y) * dst->width + x2 - dst->x) * 4;
+ put_pixel (dst_buf, mr, offset);
+ random_rgba (gr, mt);
+ offset = ((y1 - dst->y) * dst->width + xm - dst->x) * 4;
+ put_pixel (dst_buf, mt, offset);
+ random_rgba (gr, mb);
+ offset = ((y2 - dst->y) * dst->width + xm - dst->x) * 4;
+ put_pixel (dst_buf, mb, offset);
+/*ugly but working*/
+ return FALSE;
+ }
+
+ if (!depth)
+ {
+ if (x1 == x2 && y1 == y2) return FALSE;
+
+ get_pixel (src_buf, src, x1, y1, tl);
+ get_pixel (src_buf, src, x1, y2, bl);
+ get_pixel (src_buf, src, x2, y1, tr);
+ get_pixel (src_buf, src, x2, y2, tr);
+
+ ran = (1.0 / (2.0 * scale_depth)) * op->turbulance;
+
+ if (xm != x1 || xm != x2)
+ {
+ /*left*/
+ average_pixel (ml, tl, bl);
+ add_random (gr, ml, ran);
+ offset = ((ym - dst->y) * dst->width + x1 - dst->x) * 4;
+ put_pixel (dst_buf, ml, offset);
+
+ /*right*/
+ if (x1 != x2)
+ {
+ average_pixel (mr, tr, br);
+ add_random (gr, mr, ran);
+ offset = ((ym - dst->y) * dst->width + x2 - dst->x) * 4;
+ put_pixel (dst_buf, mr, offset);
+ }
+ }
+
+
+ if (ym != y1 || ym != x2)
+ {
+ /*bottom*/
+ if (x1 != xm || ym != y2)
+ {
+ average_pixel (mb, bl, br);
+ add_random (gr, mb, ran);
+ offset = ((y2 - dst->y) * dst->width + xm - dst->x) *4;
+ put_pixel (dst_buf, mb, offset);
+ }
+
+ if (y1 != y2)
+ {
+ /*top*/
+ average_pixel (mt, tl, tr);
+ add_random (gr, mt, ran);
+ offset = ((y1 - dst->y)* dst->width + xm - dst->x) * 4;
+ put_pixel (dst_buf, mt, offset);
+ }
+ }
+
+ 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);
+ offset = ((ym - dst->y) * dst->width + xm - dst->x) * 4;
+ put_pixel (dst_buf, mm, offset);
+ }
+ count++;
+
+ return x2 - x1 < 3 && y2 - y1 < 3;
+ }
+
+ if (x1 < x2 || y1 < y2)
+ {
+ /*top-left*/
+ do_plasma (src_buf, src, dst_buf, dst, x1, y1, xm, ym, depth - 1,
+ scale_depth + 1, gr, op);
+ /*bottom-left*/
+ do_plasma (src_buf, src, dst_buf, dst, x1, ym, xm, y2, depth - 1,
+ scale_depth + 1, gr, op);
+ /*top-right*/
+ do_plasma (src_buf, src, dst_buf, dst, xm, y1, x2, ym, depth - 1,
+ scale_depth + 1, gr, op);
+ /*bottom-right*/
+ return do_plasma (src_buf, src, dst_buf, dst, xm, ym, x2, y2, depth - 1,
+ scale_depth + 1, gr, op);
+ }
+ else return TRUE;
+
+ return TRUE;
+}
+
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
+
+ GeglRectangle rect;
+ gfloat *src_buf;
+
+ GRand *gr = g_rand_new_with_seed (o->seed);
+ gint depth;
+ gint x, y;
+
+ rect.x = result->x - op_area->left;
+ rect.width = result->width + op_area->left + op_area->right;
+ rect.y = result->y - op_area->top;
+ rect.height = result->height + op_area->top + op_area->bottom;
+
+ src_buf = g_new0 (gfloat, rect.width * rect.height * floats_per_pixel);
+
+ gegl_buffer_get (input, 1.0, &rect, babl_format ("RGBA float"),
+ src_buf, GEGL_AUTO_ROWSTRIDE);
+
+ g_rand_set_seed (gr, o->seed);
+
+ if (result->height && result->width)
+ {
+ /*
+ * The first time only puts seed pixels (corners, center of edges,
+ * center of image)
+ */
+ x = rect.x + rect.width;
+ y = rect.y + rect.height;
+ if (rect.x < 0) rect.x = 0;
+ if (rect.y < 0) rect.y = 0;
+ do_plasma (src_buf, &rect, src_buf, &rect, rect.x, rect.y, x-1, y-1, -1, 0, gr, o);
+ /*
+ * Now we recurse through the images, going deeper each time
+ */
+ depth = 1;
+ while (!do_plasma (src_buf, &rect, src_buf, &rect, rect.x, rect.y, x-1, y-1, depth, 0, gr, o))
+ depth++;
+ }
+
+ gegl_buffer_set (output, &rect, babl_format ("RGBA float"),
+ src_buf, GEGL_AUTO_ROWSTRIDE);
+
+ g_free (src_buf);
+
+ return TRUE;
+}
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+ GeglOperationClass *operation_class;
+ GeglOperationFilterClass *filter_class;
+
+ f=fopen("tryyy","w+t");
+
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
+
+ filter_class->process = process;
+ operation_class->prepare = prepare;
+
+ 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]