GSoC GEGL Application

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi, I am applying for the GSoC GEGL operation porting task for GIMP. I am a MS Computer Science student at the University of Massachusetts: Boston. I have experimented with gegl a little bit and have some experience in C. Here is the required information, including a ripple operation that I was experimenting with a few months ago that I cleaned up to submit.

Cubism:

Algorithm Analysis

-Split image up into even tiles
-fill up image with background color
-process each tiles in random order so that the tiles overlap randomly
-shift tile a random amount depending on tile size
-resize width and height of tile by random amounts with constraints depending on tile size and tile saturation
-rotate tile a random amount
-fill polygon with a color taken by sampling the color of a corner pixel and then blending so that the rectangle gets progressively lighter from one edge to the opposite edge.

Code review

There are some calculations that are done many times when once is enough. For example, for each tile, the value cvals.tilesize/2.0 is used both for the x and y positions, but is calculated each time. This makes an additional calculation per tile. In the same loop there is also cvals.tilesize/4.0 and width/2.0 and many others. It would be ore efficient to save these calculation in temporary values in each iteration of the loop.

Fractral Trace:

-Scale down image so that it is workable within the bounds of Mandelbrot set.
-For each pixel, use the Mandelbrot set definition to determine a pixel to map from after the user defined number of iterations. This is the pixel that is confirmed to be in the Mandelbrot set after this many iterations.
-For each pixel, scale the mapping back up so that the image can be drawn, and then draw the pixel.

Code review

There is a reliance on global values that is somewhat dangerous. In particular the array dpixels, which is written to and then copied to the main pixel region. A better way might be to pass in pointers to the pixel region or the buffer to modify within the functions, which would make debugging easier.

Plasma:

-put random colors into 9 pixels in the area to be drawn on: the corners, the midpoints between the corners, and the pixel in the center.
-recursively split the image into four quadrants. For each quadrant, determine the colors of pixels at the midpoints between the corners but averaging the color of the two corner pixels and then adding a random shift in the rgb values that depends on the turbulence parameter. The color for the point in the middle of all four corners is determined by averaging the colors of all four corners (plus the random color shift). For each upper level of recursion, the corner colors will have been determined by the recursive call lower on the recursion tree. At the lowest recursive call, when the quadrant is 2x2 pixels large or less, we are done because the corners are known and there cannot be any midpoints.

Code Review

Plasma does an iteration to determine the colors of evenly spaced pixels across the drawing region. It does recursive calls at each iteration to get to the first pixels that have not been colored yet. These previous recursive calls are probably not needed as they go through work thats already been complete. A better way might be to do everything iteratively and use the depth value to determine which pixels need to be calculated next through an iterative call. This way stack overflow can still be avoided but there is no need to go through many recursive calls at each step.

Gaussian Blur:

-Blur horizontally and then vertically depending on the x and y standard deviation parameters. How it blurs depends on if it is iir or fir.
-In iir, each pixel's new value is calculated as the weighted average of three pixels in front and behind it on the row depending on if it is blurring horizontally or vertically. The weights are calculated using the standard deviation parameter and values that approximate the relevant values on a normal curve.
-The fir algorithm is similar but instead of using estimated values, generates a convolution matrix that stores the weights. The weights in the matrix are calculated using the Gaussian function so that the higher values are in the center of the matrix. For each pixel in the row, the matrix is then iterated through to calculate a weighted average of pixels around it.

Code Review

There are many arbitrary constants in the code. For example the weights in iir are calculated by doing arithmetic on the standard deviation with seemingly arbitrary values. My guess is that these values are used to approximate a normal curve at a few points, but it be better to use named constants or at least document the code so that what these values do are explicit.

---

Thank you for your time,

Hans Lo
From c7ba406ec346e4dd398e58f453440edd07a58bde Mon Sep 17 00:00:00 2001
From: Hans Lo <hansshulo@xxxxxxxxx>
Date: Fri, 8 Apr 2011 03:56:26 -0400
Subject: [PATCH] ripple experimentation with gegl

---
 operations/common/ripple-test.c |  149 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 149 insertions(+), 0 deletions(-)
 create mode 100644 operations/common/ripple-test.c

diff --git a/operations/common/ripple-test.c b/operations/common/ripple-test.c
new file mode 100644
index 0000000..dc62973
--- /dev/null
+++ b/operations/common/ripple-test.c
@@ -0,0 +1,149 @@
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_int (amplitude, _("Amplitude"), 0, 200, 50,
+   _("Amplitude of ripple."))
+
+gegl_chant_int (period, _("Period"), 0, 200, 50,
+   _("Period of ripple."))
+
+gegl_chant_double (phi, _("Phase Shift"), -1.0, 1.0, 0.0,
+   _("As proportion of pi."))
+
+gegl_chant_boolean (antialias,   _("Antialiasing"),   FALSE,
+                    _("Antialiasing"))
+
+#else
+
+#define GEGL_CHANT_TYPE_AREA_FILTER
+#define GEGL_CHANT_C_FILE       "ripple-test.c"
+
+#include "gegl-chant.h"
+#include <stdio.h>
+#include <math.h>
+
+
+static gdouble
+displace_amount (gint location, gint amplitude, gint period, gdouble phi)
+{
+  return ((gdouble)amplitude *
+	  sin (2 * G_PI * (((gdouble)location / (gdouble)period) + G_PI*phi)));
+}
+
+static void
+horizontal_shift (GeglBuffer          *src,
+      const GeglRectangle *src_rect,
+      GeglBuffer          *dst,
+      const GeglRectangle *dst_rect,
+      gint amplitude,
+      gint period,
+      gdouble phi,
+      gboolean antialias)
+{
+  gint u,v;
+  gint src_offset, dst_offset;
+  gfloat *src_buf;
+  gfloat *dst_buf;
+  src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 4);
+  dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4);
+  gegl_buffer_get (src, 1.0, src_rect, babl_format ("RaGaBaA float"), src_buf, GEGL_AUTO_ROWSTRIDE);
+  src_offset = 0;
+  dst_offset = 0;
+  for (v=0; v<dst_rect->height; v++)
+    {
+      gdouble shift = displace_amount(v+dst_rect->y, amplitude, period, phi);
+      gdouble floor_shift = floor(shift);
+      gdouble remainder = shift-floor_shift;
+      gdouble temp_value;
+      
+      for (u=0; u<(dst_rect->width); u++)
+        {
+          gint i;
+      
+          for (i=0; i<4; i++)
+            {
+              gint new_pixel = src_offset + (4*amplitude + 4*amplitude*2*v + 4*(gint)floor_shift);
+              //antialias
+
+      
+              temp_value = src_buf[new_pixel];
+
+              if(antialias && u>3 && i < 3)
+                {
+                  gint upper_pixel = new_pixel - 4;
+                  temp_value = (remainder)*src_buf[new_pixel] + (1.0-remainder)*src_buf[upper_pixel];
+      
+                }
+      
+              dst_buf[dst_offset] = temp_value;
+              src_offset++;
+              dst_offset++;
+            }
+        }
+    }
+
+  gegl_buffer_set (dst, dst_rect, babl_format ("RaGaBaA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
+  g_free (src_buf);
+  g_free (dst_buf);
+}
+
+static void prepare (GeglOperation *operation)
+{
+  GeglChantO              *o;
+  GeglOperationAreaFilter *op_area;
+
+  op_area = GEGL_OPERATION_AREA_FILTER (operation);
+  o       = GEGL_CHANT_PROPERTIES (operation);
+
+    op_area->left   =
+    op_area->right  = o->amplitude;
+    //op_area->top    =
+    //op_area->bottom = 
+
+  gegl_operation_set_format (operation, "output",
+                             babl_format ("RaGaBaA float"));
+
+}
+
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         GeglBuffer          *output,
+         const GeglRectangle *result)
+{
+
+  GeglRectangle rect;
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+  GeglOperationAreaFilter *op_area;
+  op_area = GEGL_OPERATION_AREA_FILTER (operation);
+
+  rect = *result;
+
+  rect.x-=op_area->left;
+  rect.width+=op_area->left + op_area->right;
+  horizontal_shift(input, &rect, output, result, o->amplitude, o->period, o->phi, o->antialias);
+  return  TRUE;
+}
+
+
+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->categories  = "blur";
+  operation_class->name        = "gegl:ripple-test";
+  operation_class->description =
+       _("Trying out GEGL.");
+}
+
+#endif
-- 
1.7.4.1

_______________________________________________
Gimp-developer mailing list
Gimp-developer@xxxxxxxxxxxxxxxxxxxxxx
https://lists.XCF.Berkeley.EDU/mailman/listinfo/gimp-developer

[Index of Archives]     [Video For Linux]     [Photo]     [Yosemite News]     [gtk]     [GIMP for Windows]     [KDE]     [GEGL]     [Gimp's Home]     [Gimp on GUI]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux