[gegl] Port tile-glass to GEGL
- From: Daniel Sabo <daniels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Port tile-glass to GEGL
- Date: Fri, 16 May 2014 10:39:02 +0000 (UTC)
commit a61c116873d74b8c7eaee30836a59bc1fe05ebd3
Author: Denis Knoepfle <penpal denis web de>
Date: Fri May 16 03:31:18 2014 -0700
Port tile-glass to GEGL
operations/common/Makefile.am | 1 +
operations/common/tile-glass.c | 251 ++++++++++++++++++++++++++++++++++++++++
po/POTFILES.in | 1 +
3 files changed, 253 insertions(+), 0 deletions(-)
---
diff --git a/operations/common/Makefile.am b/operations/common/Makefile.am
index b798037..1b7a5ad 100644
--- a/operations/common/Makefile.am
+++ b/operations/common/Makefile.am
@@ -111,6 +111,7 @@ op_LTLIBRARIES = \
threshold.la \
tile-seamless.la \
tile.la \
+ tile-glass.la \
unsharp-mask.la \
value-invert.la \
vignette.la \
diff --git a/operations/common/tile-glass.c b/operations/common/tile-glass.c
new file mode 100644
index 0000000..cf31a00
--- /dev/null
+++ b/operations/common/tile-glass.c
@@ -0,0 +1,251 @@
+/* This file is an image processing operation for GEGL
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Contains code originaly from GIMP tile-glass.c, copyright
+ * Karl-Johan Andersson and Tim Copperfield.
+ *
+ * Glass Tile (sequential version) ported to GEGL:
+ * Copyright 2014 Denis Knoepfle
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_int (tileWidth, _("Tile Width"),
+ 10, 50, 25,
+ _("Tile Width"))
+
+gegl_chant_int (tileHeight, _("Tile Height"),
+ 10, 50, 25,
+ _("Tile Height"))
+
+#else
+
+#define GEGL_CHANT_TYPE_AREA_FILTER
+#define GEGL_CHANT_C_FILE "tile-glass.c"
+
+#include "gegl-chant.h"
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+static void
+prepare (GeglOperation *operation)
+{
+ const Babl *input_format = gegl_operation_get_source_format (operation, "input");
+ const Babl *format;
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+
+ GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation);
+
+ if (input_format == NULL || babl_format_has_alpha (input_format))
+ format = babl_format ("R'G'B'A float");
+ else
+ format = babl_format ("R'G'B' float");
+
+ area->left = area->right = o->tileWidth - 1;
+ area->top = area->bottom = o->tileHeight - 1;
+
+ gegl_operation_set_format (operation, "input", format);
+ gegl_operation_set_format (operation, "output", format);
+}
+
+static GeglRectangle
+get_bounding_box (GeglOperation *operation)
+{
+ GeglRectangle *region;
+
+ region = gegl_operation_source_get_bounding_box (operation, "input");
+
+ if (region != NULL)
+ return *region;
+ else
+ return *GEGL_RECTANGLE (0, 0, 0, 0);
+}
+
+static void
+tile_glass (GeglBuffer *src,
+ GeglBuffer *dst,
+ const GeglRectangle *dst_rect, /* region of interest */
+ const Babl *format,
+ gint tileWidth,
+ gint tileHeight)
+{
+ gint components;
+ gfloat *src_row_buf;
+ gfloat *dst_row_buf;
+ const GeglRectangle *extent;
+ GeglRectangle src_bufrect, dst_bufrect;
+
+ gint row, col, i;
+ gint x1, y1, y2;
+ gint dst_xoffs, src_x0, xright_abyss, src_rowwidth;
+
+ gint xpixel1, xpixel2;
+ gint ypixel2;
+ gint xhalf, xoffs, xmiddle, xplus;
+ gint yhalf, yoffs, ymiddle, yplus;
+
+ extent = gegl_buffer_get_extent (dst);
+
+ x1 = dst_rect->x;
+ y1 = dst_rect->y;
+ y2 = y1 + dst_rect->height;
+
+ xhalf = tileWidth / 2;
+ yhalf = tileHeight / 2;
+
+ xplus = tileWidth % 2;
+ yplus = tileHeight % 2;
+
+ dst_xoffs = x1 % tileWidth + xplus;
+ src_x0 = x1 - dst_xoffs;
+ xright_abyss = 2 * ((x1 + dst_rect->width) % tileWidth);
+ if (xright_abyss > tileWidth - 2)
+ xright_abyss = tileWidth - 2;
+ src_rowwidth = dst_xoffs + dst_rect->width + xright_abyss;
+
+ yoffs = y1 % tileHeight;
+ ymiddle = y1 - yoffs;
+ if (yoffs >= yhalf)
+ {
+ ymiddle += tileHeight;
+ yoffs -= tileHeight;
+ }
+
+ components = babl_format_get_n_components (format);
+
+ src_row_buf = g_new (gfloat, src_rowwidth * components);
+ dst_row_buf = g_new (gfloat, dst_rect->width * components);
+ gegl_rectangle_set (&src_bufrect, src_x0, 0, src_rowwidth, 1);
+ gegl_rectangle_set (&dst_bufrect, x1, 0, dst_rect->width, 1);
+
+ /* loop through rows */
+ for (row = y1; row < y2; ++row)
+ {
+ /* no need to clamp as abyss policy does that */
+ ypixel2 = ymiddle + yoffs * 2;
+
+ src_bufrect.y = ypixel2;
+ gegl_buffer_get (src, &src_bufrect, 1.0, format, src_row_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
+
+ yoffs++;
+
+ /* if current offset = half, do a displacement next time around */
+ if (yoffs == yhalf)
+ {
+ ymiddle += tileHeight;
+ yoffs = - (yhalf + yplus);
+ }
+
+ xoffs = x1 % tileWidth;
+ xmiddle = x1 - xoffs;
+ if (xoffs >= xhalf)
+ {
+ xmiddle += tileWidth;
+ xoffs -= tileWidth;
+ }
+
+ /* loop through columns */
+ for (col = 0; col < dst_rect->width; ++col)
+ {
+ xpixel1 = (xmiddle + xoffs - x1) * components;
+ if (xmiddle + xoffs * 2 + dst_xoffs < extent->width)
+ {
+ xpixel2 = (xmiddle + xoffs * 2 - x1 + dst_xoffs) * components;
+ }
+ else
+ {
+ xpixel2 = (xmiddle + xoffs - x1 + dst_xoffs) * components;
+ }
+
+ for (i = 0; i < components; ++i)
+ {
+ dst_row_buf[xpixel1 + i] = src_row_buf[xpixel2 + i];
+ }
+
+ xoffs++;
+
+ if (xoffs == xhalf)
+ {
+ xmiddle += tileWidth;
+ xoffs = - (xhalf + xplus);
+ }
+ }
+
+ /* write result row to dest */
+ dst_bufrect.y = row;
+ gegl_buffer_set (dst, &dst_bufrect, 0, format, dst_row_buf, GEGL_AUTO_ROWSTRIDE);
+ }
+
+ g_free (src_row_buf);
+ g_free (dst_row_buf);
+}
+
+static gboolean
+process (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
+ const Babl *format = gegl_operation_get_format (operation, "input");
+
+ tile_glass (input, output, result, format, o->tileWidth, o->tileHeight);
+
+ return TRUE;
+}
+
+static void
+finalize (GObject *object)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (object);
+
+ if (o->chant_data)
+ {
+ o->chant_data = NULL;
+ }
+
+ G_OBJECT_CLASS (gegl_chant_parent_class)->finalize (object);
+}
+
+static void
+gegl_chant_class_init (GeglChantClass *klass)
+{
+ GObjectClass *object_class;
+ GeglOperationClass *operation_class;
+ GeglOperationFilterClass *filter_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ operation_class = GEGL_OPERATION_CLASS (klass);
+ filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
+
+ object_class->finalize = finalize;
+ operation_class->prepare = prepare;
+ operation_class->get_bounding_box = get_bounding_box;
+ filter_class->process = process;
+
+ gegl_operation_class_set_keys (operation_class,
+ "categories", "artistic",
+ "license", "GPL3+",
+ "name", "gegl:tile-glass",
+ "description", _("Creates the effect of watching on the picture through thick glass "),
+ NULL);
+}
+
+#endif
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6d1b72d..33ae2c6 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -103,6 +103,7 @@ operations/common/svg-saturate.c
operations/common/texturize-canvas.c
operations/common/threshold.c
operations/common/tile.c
+operations/common/tile-glass.c
operations/common/tile-seamless.c
operations/common/unsharp-mask.c
operations/common/value-invert.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]