[gegl] Add mirrors op to workshop that implements GIMP kaleidoskope pluging for gegl



commit ec67d293c323020616aabfaecfb932b63b61e584
Author: Alexia Death <alexiadeath gmail com>
Date:   Sat Jan 30 17:11:27 2010 +0200

    Add mirrors op to workshop that implements GIMP kaleidoskope pluging for gegl
    
    Plugin has some border issues to bi fixed. Also interpolation
    using gegl buffer samping is awfully slow.

 operations/workshop/mirrors.c |  339 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 339 insertions(+), 0 deletions(-)
---
diff --git a/operations/workshop/mirrors.c b/operations/workshop/mirrors.c
new file mode 100644
index 0000000..89b6517
--- /dev/null
+++ b/operations/workshop/mirrors.c
@@ -0,0 +1,339 @@
+/* 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/>.
+ *
+ * Copyright 2006 �yvind Kolås <pippin gimp org>
+ * Copyright 2010 Alexia Death
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_double (m_angle, _("Mirror rotation"), 0.0, 180.0, 0.0, _("Rotation applied to the mirrors"))
+
+gegl_chant_double (r_angle, _("Result rotation"), 0.0, 360.0, 0.0, _("Rotation applied to the result"))
+
+gegl_chant_int    (n_segs, _("Mirrors"), 2, 24, 6, _("Number of mirrors to use"))
+
+gegl_chant_double (c_x,  _("X offset"), 0.0, 1.0, 0.5, _("X offset of the result of mirroring"))
+
+gegl_chant_double (c_y,  _("Y offset"), 0.0, 1.0, 0.5, _("Y offset of the result of mirroring"))
+
+gegl_chant_double (o_x, _("Center X"), -1.0, 1.0, 0.0, _("X axis ratio for the center of mirroring"))
+
+gegl_chant_double (o_y, _("Center Y"), -1.0, 1.0, 0.0, _("Y axis ratio for the center of mirroring"))
+
+gegl_chant_boolean (clip, _("Clip result"), TRUE, _("Clip result to input size"))
+
+gegl_chant_boolean (warp, _("Wrap input"), TRUE, _("Fill full output area"))
+
+
+#else
+
+#define GEGL_CHANT_TYPE_FILTER
+#define GEGL_CHANT_C_FILE       "mirrors.c"
+
+#include "gegl-chant.h"
+#include <math.h>
+#include "lens-correct.h"
+
+#if 1
+#define TRACE       /* Define this to see basic tracing info. */
+#endif
+
+#if 0
+#define DO_NOT_USE_BUFFER_SAMPLE       /* Define this to see basic tracing info. */
+#endif
+
+static int
+calc_undistorted_coords(double wx, double wy,
+                        double angle1, double angle2, int nsegs,
+                        double cen_x, double cen_y,
+                        double off_x, double off_y,
+                        double *x, double *y)
+{
+  double dx, dy;
+  double r, ang;
+
+  double awidth = G_PI/nsegs;
+  double mult;
+
+  dx = wx - cen_x;
+  dy = wy - cen_y;
+
+  r = sqrt(dx*dx+dy*dy);
+  if (r == 0.0) {
+    *x = wx + off_x;
+    *y = wy + off_y;
+    return TRUE;
+  }
+
+  ang = atan2(dy,dx) - angle1 - angle2;
+  while (ang<0.0) ang = ang + 2*G_PI;
+
+  mult = ceil(ang/awidth) - 1;
+  ang = ang - mult*awidth;
+  if (((int) mult) % 2 == 1) ang = awidth - ang;
+  ang = ang + angle1;
+
+  *x = r*cos(ang) + off_x;
+  *y = r*sin(ang) + off_y;
+
+  return TRUE;
+} /* calc_undistorted_coords */
+
+/* Apply the actual transform */
+
+static void
+apply_mirror (double mirror_angle,
+              double result_angle,
+              int nsegs,
+              double cen_x,
+              double cen_y,
+              double off_x,
+              double off_y,
+              gboolean clip,
+              gboolean warp,
+              GeglBuffer *src,
+              GeglBuffer *dst,
+              GeglRectangle *boundary,
+              GeglRectangle *roi)
+{
+  const GeglRectangle *src_extent;
+  const GeglRectangle *dst_extent;
+  gfloat *src_buf;
+  gfloat *dst_buf;
+  gint row, col, spx_pos, dpx_pos, ix, iy;
+  gdouble cx, cy;
+
+
+  /* Get src pixels. */
+  //
+
+  #ifdef TRACE
+    g_warning ("> mirror marker1, boundary x:%d, y:%d, w:%d, h:%d, center: (%f, %f) offset: (%f, %f)", boundary->x, boundary->y, boundary->width, boundary->height, cen_x, cen_y, off_x,off_y );
+  #endif
+
+  #ifdef DO_NOT_USE_BUFFER_SAMPLE
+    src_buf = g_new0 (gfloat, boundary->width * boundary->height * 4);
+    gegl_buffer_get (src, 1.0, boundary, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE);
+  #endif
+  /* Get buffer in which to place dst pixels. */
+  dst_buf = g_new0 (gfloat, roi->width * roi->height * 4);
+
+  mirror_angle   = mirror_angle * G_PI / 180;
+  result_angle   = result_angle * G_PI / 180;
+
+  for (row = 0; row < roi->height; row++) {
+    for (col = 0; col < roi->width; col++) {
+        calc_undistorted_coords(roi->x + col, roi->y + row, mirror_angle, result_angle,
+                                  nsegs,
+                                  cen_x, cen_y,
+                                  off_x, off_y,
+                                  &cx, &cy);
+
+        Babl *format = babl_format ("RGBA float");
+        gfloat pixel[4];
+
+        /*Warping*/
+        if (warp) {
+                while (cx < 0)
+                        cx = cx + boundary->width;
+                while (cy < 0)
+                        cy = cy + boundary->height;
+
+                while (cx >= boundary->width)
+                        cx = cx - boundary->width;
+                while (cy >= boundary->height)
+                        cy = cy - boundary->height;
+        }
+        else {
+                while (cx < 0)
+                        cx = 0;
+                while (cy < 0)
+                        cy = 0;
+
+                while (cx >= boundary->width)
+                        cx = boundary->width - 1;
+                while (cy >= boundary->height)
+                        cy = boundary->height -1;
+        }
+
+        /* Top */
+#ifdef DO_NOT_USE_BUFFER_SAMPLE
+
+        if (cx >= 0.0)
+          ix = (int) cx;
+        else
+          ix = -((int) -cx + 1);
+
+        if (cy >= 0.0)
+          iy = (int) cy;
+        else
+          iy = -((int) -cy + 1);
+
+        spx_pos = (iy * boundary->width + ix) * 4;
+#endif
+
+        /* g_warning ("> mirror marker 3: src: (%d,%d):%d-> (%d,%d):%d", ix, iy, spx_pos, col,row, dpx_pos); */
+
+#ifndef DO_NOT_USE_BUFFER_SAMPLE
+        gegl_buffer_sample (src, cx, cy, 1.0, &dst_buf[(row * roi->width + col) * 4], format,  GEGL_INTERPOLATION_LINEAR);
+#endif
+
+#ifdef DO_NOT_USE_BUFFER_SAMPLE
+         dst_buf[dpx_pos]     = src_buf[spx_pos];
+         dst_buf[dpx_pos + 1] = src_buf[spx_pos + 1];
+         dst_buf[dpx_pos + 2] = src_buf[spx_pos + 2];
+         dst_buf[dpx_pos + 3] = src_buf[spx_pos + 3];
+#endif
+
+    } /* for */
+
+  } /* for */
+
+    gegl_buffer_sample_cleanup(src);
+
+  /* Store dst pixels. */
+  gegl_buffer_set (dst, roi, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE);
+
+  gegl_buffer_flush(dst);
+
+  /* Free acquired storage. */
+#ifdef DO_NOT_USE_BUFFER_SAMPLE
+  g_free (src_buf);
+#endif
+  g_free (dst_buf);
+
+}
+
+/*****************************************************************************/
+
+/* Compute the region for which this operation is defined.
+ */
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+  GeglRectangle  result = {0,0,0,0};
+  GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input");
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+
+  if (!in_rect){
+        return result;
+  }
+
+  if (o->clip) {
+    gegl_rectangle_copy(&result, in_rect);
+  }
+  else {
+    result.x = in_rect->x;
+    result.y = in_rect->y;
+    result.width = result.height = sqrt (in_rect->width * in_rect->width + in_rect->height * in_rect->height) * MAX ((o->o_x + 1),  (o->o_y + 1)) * 2;
+  }
+
+  #ifdef TRACE
+    g_warning ("< get_bounding_box result = %dx%d+%d+%d", result.width, result.height, result.x, result.y);
+  #endif
+  return result;
+}
+
+/* Compute the input rectangle required to compute the specified region of interest (roi).
+ */
+static GeglRectangle
+get_required_for_output (GeglOperation       *operation,
+                         const gchar         *input_pad,
+                         const GeglRectangle *roi)
+{
+
+  GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input");
+  GeglRectangle  result;
+  gegl_rectangle_copy(&result, in_rect);
+  #ifdef TRACE
+    g_warning ("> get_required_for_output src=%dx%d+%d+%d", result.width, result.height, result.x, result.y);
+    if (roi)
+      g_warning ("  ROI == %dx%d+%d+%d", roi->width, roi->height, roi->x, roi->y);
+  #endif
+
+  return result;
+}
+
+/* Specify the input and output buffer formats.
+ */
+static void
+prepare (GeglOperation *operation)
+{
+  #ifdef TRACE
+    g_warning ("> prepare");
+  #endif
+  gegl_operation_set_format (operation, "input", babl_format ("RGBA float"));
+  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+  #ifdef TRACE
+    g_warning ("< prepare");
+  #endif
+}
+
+/* Perform the specified operation.
+ */
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         GeglBuffer          *output,
+         const GeglRectangle *result)
+{
+  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+  GeglRectangle boundary = gegl_operation_get_bounding_box (operation);
+#ifdef DO_NOT_USE_BUFFER_SAMPLE
+ g_warning ("NOT USING BUFFER SAMPLE!");
+#endif
+  apply_mirror (o->m_angle,
+                o->r_angle,
+                o->n_segs,
+                o->c_x * boundary.width,
+                o->c_y * boundary.height,
+                o->o_x * boundary.width,
+                o->o_y * boundary.height,
+                o->clip,
+                o->warp,
+                input,
+                output,
+                &boundary,
+                result);
+  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->get_bounding_box = get_bounding_box;
+  operation_class->get_required_for_output = get_required_for_output;
+
+  operation_class->name        = "gegl:mirrors";
+  operation_class->categories  = "blur";
+  operation_class->description =
+        _("Applies mirroring effect on the image.");
+}
+
+#endif



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