[gegl/soc-2011-ops] Added the plasma op (with bugs)



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]