[PATCH][Operation] Port of paper-tile from GIMP to gegl

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

 



Hi all,
I have ported a plugin called 'paper-tile' to gegl. This is my first contribution so I want anyone of you to review it.

Thanks,
~akash akya
From d8679242299b6421dbffb1504778c6a1a4efdf65 Mon Sep 17 00:00:00 2001
From: akash akya <akashh246@xxxxxxxxx>
Date: Thu, 30 Apr 2015 11:57:22 +0530
Subject: [PATCH] operations: add gegl:paper-tile. Port from GIMP to gegl

---
 operations/common/Makefile.am  |   1 +
 operations/common/paper-tile.c | 434 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 435 insertions(+)
 create mode 100644 operations/common/paper-tile.c

diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index 7beab1e..c68405e 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -102,6 +102,7 @@ op_LTLIBRARIES = \
 	over.la \
 	panorama-projection.la \
 	photocopy.la \
+	paper-tile.la \
 	pixelize.la \
 	plasma.la \
 	polar-coordinates.la \
diff --git a/operations/common/paper-tile.c b/operations/common/paper-tile.c
new file mode 100644
index 0000000..3eb4360
--- /dev/null
+++ b/operations/common/paper-tile.c
@@ -0,0 +1,434 @@
+/* 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/>.
+ *
+ * Contains code originaly from GIMP tile-paper.c, copyright
+ * Copyright 1997-1999 Hirotsuna Mizuno <s1041150@xxxxxxxxxxxx>
+ *
+ * Tile paper ported to GEGL:
+ * Copyright 2015 Akash Hiremath (akash akya) <akashh246@xxxxxxxxx>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+#include <stdlib.h>
+
+
+#ifdef GEGL_PROPERTIES
+
+enum_start (gegl_tile_paper_background_type)
+  enum_value (GEGL_BACKGROUND_TYPE_TRANSPARENT, "transparent", N_("Transparent"))
+  enum_value (GEGL_BACKGROUND_TYPE_INVERT,  "invert",  N_("Invert"))
+  enum_value (GEGL_BACKGROUND_TYPE_IMAGE,  "image",  N_("Image"))
+  enum_value (GEGL_BACKGROUND_TYPE_COLOR,  "color",  N_("Color"))
+enum_end (Gegl_tile_paper_background_type)
+
+enum_start (gegl_fractional_type)
+  enum_value (GEGL_FRACTIONAL_TYPE_BACKGROUND, "background", N_("Background"))
+  enum_value (GEGL_FRACTIONAL_TYPE_IGNORE,  "ignore",  N_("Ignore"))
+  enum_value (GEGL_FRACTIONAL_TYPE_FORCE,  "force",  N_("Force"))
+enum_end (Gegl_fractional_type)
+
+property_int (tile_width, _("Tile Width"), 155)
+    description (_("Width of the tile"))
+    value_range (1, G_MAXINT)
+    ui_range    (1, 1500)
+    ui_meta     ("unit", "pixel-distance")
+    ui_meta     ("axis", "x")
+
+property_int (tile_height, _("Tile Height"), 56)
+    description (_("Height of the tile"))
+    value_range (1, G_MAXINT)
+    ui_range    (1, 1500)
+    ui_meta     ("unit", "pixel-distance")
+    ui_meta     ("axis", "y")
+
+property_double (move_rate, _("Move rate"), 25.0)
+    description (_("Move rate"))
+    value_range (1.0, 100.0)
+    ui_range    (1.0, 100.0)
+    ui_meta     ("unit", "percent")
+
+property_color  (bg_color, _("Background color"), "rgba(0.0, 0.0, 0.0, 1.0)")
+    description (("The tiles' background color"))
+    ui_meta     ("role", "color-primary")
+
+property_boolean (centering, _("Centering"), FALSE)
+    description(_("Centering of the tiles"))
+
+property_enum  (tile_paper_background_type, _("Background type"),
+    Gegl_tile_paper_background_type, gegl_tile_paper_background_type,
+    GEGL_BACKGROUND_TYPE_INVERT)
+    description (_("Background type"))
+
+property_enum  (fractional_type, _("Fractional type"),
+    Gegl_fractional_type, gegl_fractional_type,
+    GEGL_FRACTIONAL_TYPE_FORCE)
+    description (_("Fractional Type"))
+
+#else
+
+#define GEGL_OP_AREA_FILTER
+#define GEGL_OP_C_SOURCE paper-tile.c
+
+#include "gegl-op.h"
+#include <math.h>
+#include <stdio.h>
+
+
+typedef struct _Tile
+{
+  guint x;
+  guint y;
+  gint  z;
+  guint width;
+  guint height;
+  gint  move_x;
+  gint  move_y;
+} Tile;
+
+
+static gint
+tile_compare (const void *x,
+              const void *y)
+{
+  return ((Tile *) x)->z - ((Tile *) y)->z;
+}
+
+
+
+static inline void
+random_move (gint *x,
+             gint *y,
+             gint  max,
+             GRand *gr)
+{
+  gdouble angle  = g_rand_double_range (gr, 0.0, 1.0) * G_PI;
+  gdouble radius = g_rand_double_range (gr, 0.0, 1.0) * (gdouble) max;
+  *x = (gint) (radius * cos (angle));
+  *y = (gint) (radius * sin (angle));
+}
+
+
+
+static void
+prepare (GeglOperation *operation)
+{
+  GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
+  GeglProperties          *o       = GEGL_PROPERTIES (operation);
+
+  op_area->left   = o->tile_width;
+  op_area->right  = o->tile_width;
+  op_area->top    = o->tile_height;
+  op_area->bottom = o->tile_height;
+
+  gegl_operation_set_format (operation, "input",  babl_format ("RGBA float"));
+  gegl_operation_set_format (operation, "output", babl_format ("RGBA float"));
+}
+
+static void 
+randomize_tiles  (  GeglProperties      *o,
+                    const     GeglRectangle *rect, 
+                    gint      division_x,
+                    gint      division_y,
+                    gint      offset_x,
+                    gint      offset_y,
+                    gint      numof_tiles,  
+                    Tile     *tiles)
+{
+  Tile    *t = tiles;
+  gint     move_max_pixels = o->move_rate * o->tile_width / 100;
+  
+  gint     x;
+  gint     y;
+  GRand   *gr;
+
+  gr = g_rand_new ();
+
+   for (y = 0; y < division_y; y++)
+    {
+      gint srcy = offset_y + o->tile_height * y;
+
+      for (x = 0; x < division_x; x++, t++)
+        {
+          gint srcx = offset_x + o->tile_width * x;
+
+          if (srcx < 0)
+            {
+              t->x     = 0;
+              t->width = srcx + o->tile_width;
+            }
+          else if (srcx + o->tile_width < rect->width)
+            {
+              t->x     = srcx;
+              t->width = o->tile_width;
+            }
+          else
+            {
+              t->x     = srcx;
+              t->width = rect->width - srcx;
+            }
+
+          if (srcy < 0)
+            {
+              t->y      = 0;
+              t->height = srcy + o->tile_height;
+            }
+          else if (srcy + o->tile_height < rect->height)
+            {
+              t->y      = srcy;
+              t->height = o->tile_height;
+            }
+          else
+            {
+              t->y      = srcy;
+              t->height = rect->height - srcy;
+            }
+
+          t->z = g_rand_int (gr);
+          random_move (&t->move_x, &t->move_y, move_max_pixels, gr);
+        }
+    }
+    qsort (tiles, numof_tiles, sizeof *tiles, tile_compare);
+}
+
+static void 
+draw_tiles (  GeglProperties *o,
+              GeglBuffer     *input,
+              GeglBuffer     *output,
+              gint            num_of_tiles,
+              Tile           *tiles)
+{
+  const   Babl *format;
+  gfloat *tile_buffer;
+  Tile   *t;
+  gint    i;
+
+  format = babl_format ("RGBA float");
+  tile_buffer = g_new0 (gfloat, 4 * o->tile_width * o->tile_height);
+
+  for (t = tiles, i = 0; i < num_of_tiles; i++, t++)
+    {
+      GeglRectangle tile_rect = {t->x, t->y, t->width, t->height};
+      gegl_buffer_get (input, &tile_rect, 1.0, format, tile_buffer,
+                                    GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+      tile_rect.x += t->move_x;
+      tile_rect.y += t->move_y;
+      gegl_buffer_set (output, &tile_rect, 0, format,
+                             tile_buffer, GEGL_AUTO_ROWSTRIDE);
+    }
+
+  g_free (tile_buffer);
+}
+
+static void 
+set_background (  GeglProperties      *o,
+                  const GeglRectangle *rect,
+                  GeglBuffer          *input,
+                  GeglBuffer          *output,
+                  gint                 division_x,
+                  gint                 division_y,
+                  gint                 offset_x,
+                  gint                 offset_y)
+{
+  gint        x; 
+  gint        y; 
+  gint        index;
+  gint        clear_x0; 
+  gint        clear_y0; 
+  gint        clear_x1;
+  gint        clear_y1;
+  gfloat     *dest_buf;
+  gfloat     *buf;
+  const Babl *format;
+
+  format = babl_format ("RGBA float");
+  dest_buf = g_new0 (gfloat, 4 * rect->width * rect->height);
+
+  if (o->fractional_type == GEGL_FRACTIONAL_TYPE_IGNORE)
+    {
+      clear_x0     = offset_x;
+      clear_y0     = offset_y;
+      clear_x1     = clear_x0 + o->tile_width * (rect->width / o->tile_width);
+      clear_y1     = clear_y0 + o->tile_height * (rect->height / o->tile_height);
+    }
+  else
+    {
+      clear_x0     = 0;
+      clear_y0     = 0;
+      clear_x1     = clear_x0 + rect->width;
+      clear_y1     = clear_y0 + rect->height;
+    }
+
+  switch (o->tile_paper_background_type)
+    {
+    case GEGL_BACKGROUND_TYPE_TRANSPARENT:
+        gegl_buffer_set_color (output, rect, 
+                        gegl_color_new ("rgba(0.0,0.0,0.0,0.0)"));
+      break;
+
+    case GEGL_BACKGROUND_TYPE_COLOR:
+        gegl_buffer_set_color (output, rect, o->bg_color);
+      break;
+
+    case GEGL_BACKGROUND_TYPE_INVERT:
+        gegl_buffer_get (input, rect, 1.0, format, dest_buf,
+                                    GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+        buf = dest_buf;
+        for (y = clear_y0; y < clear_y1; y++)
+        {
+          for (x = clear_x0; x < clear_x1; x++)
+            {
+              index         = 4 * (y * rect->width + x);
+              buf[index]    = 1 - buf[index];
+              buf[index+1]  = 1 - buf[index+1];
+              buf[index+2]  = 1 - buf[index+2];
+            }
+        }
+        gegl_buffer_set (output, rect, 0, format, dest_buf, GEGL_AUTO_ROWSTRIDE);
+      break;
+
+    case GEGL_BACKGROUND_TYPE_IMAGE:
+        gegl_buffer_get (input, rect, 1.0, format, dest_buf,
+                                    GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
+        gegl_buffer_set (output, rect, 0, format, dest_buf, GEGL_AUTO_ROWSTRIDE);
+      break;
+    }
+
+  g_free (dest_buf);
+}
+
+static gboolean
+process (GeglOperation       *operation,
+         GeglBuffer          *input,
+         GeglBuffer          *output,
+         const GeglRectangle *result,
+         gint                 level)
+{
+  GeglProperties  *o = GEGL_PROPERTIES (operation);
+
+  Tile* tiles;
+  gint offset_x;
+  gint offset_y;
+  gint division_x;
+  gint division_y;
+  gint numof_tiles;
+
+  division_x = result->width / o->tile_width;
+  division_y = result->height / o->tile_height;
+
+  offset_x = 0;
+  offset_y = 0;
+
+  if (o->fractional_type == GEGL_FRACTIONAL_TYPE_FORCE)
+    {
+      if (0 < result->width  % o->tile_width) division_x++;
+      if (0 < result->height % o->tile_height) division_y++;
+      if (o->centering)
+        {
+          if (1 < result->width % o->tile_width)
+            {
+              division_x++;
+              offset_x = (result->width % o->tile_width) / 2 - o->tile_width;
+            }
+         
+          if (1 < result->height % o->tile_height)
+            {
+              division_y++;
+              offset_y = (result->height % o->tile_height) / 2 - o->tile_height;
+            }
+        }
+    }
+  else
+    {
+      if (o->centering)
+        {
+          offset_x = (result->width  % o->tile_width) / 2;
+          offset_y = (result->height % o->tile_height) / 2;
+        }
+    }
+
+  numof_tiles = division_x * division_y;
+  tiles = g_new(Tile, numof_tiles);
+
+  randomize_tiles (o, result,  division_x, division_y, 
+                            offset_x, offset_y, numof_tiles, tiles);
+  set_background  (o, result, input, output, division_x, division_y,
+                            offset_x, offset_y);
+
+  draw_tiles(o, input, output, numof_tiles, tiles);
+  return  TRUE;
+}
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+  GeglRectangle  result  = {0,0,0,0};
+  GeglRectangle *in_rect = gegl_operation_source_get_bounding_box (operation, "input");
+
+  if (!in_rect)
+  {
+    return result;
+  }
+
+  gegl_rectangle_copy (&result, in_rect);
+  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  result = get_bounding_box (operation);
+  return result;
+}
+
+static GeglRectangle
+get_cached_region (GeglOperation       *operation,
+                   const GeglRectangle *roi)
+{
+  return *gegl_operation_source_get_bounding_box (operation, "input");
+}
+
+
+
+static void
+gegl_op_class_init (GeglOpClass *klass)
+{
+  GeglOperationClass       *operation_class;
+  GeglOperationFilterClass *filter_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  filter_class    = GEGL_OPERATION_FILTER_CLASS (klass);
+
+  operation_class->prepare        = prepare;
+  filter_class->process           = process;
+  operation_class->threaded                = FALSE;
+  operation_class->get_bounding_box        = get_bounding_box;
+  operation_class->get_required_for_output = get_required_for_output;
+  operation_class->get_cached_region       = get_cached_region;
+  
+  gegl_operation_class_set_keys (operation_class,
+    "name",        "gegl:paper-tile",
+    "title",       _("Paper Tile"),
+    "categories",  "artistic",
+    "description", _("Distort"),
+    NULL);
+}
+
+#endif
-- 
1.9.1

_______________________________________________
gegl-developer-list mailing list
List address:    gegl-developer-list@xxxxxxxxx
List membership: https://mail.gnome.org/mailman/listinfo/gegl-developer-list


[Index of Archives]     [Yosemite News]     [Yosemite Photos]     [gtk]     [GIMP Users]     [KDE]     [Gimp's Home]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux