[gegl] Add rotate-on-center operation
- From: Jon Nordby <jonnor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] Add rotate-on-center operation
- Date: Wed, 30 Sep 2015 14:55:58 +0000 (UTC)
commit c7f4aba65657b4a7a0df47c97006bd34d188d336
Author: Vilson Vieira <vilson void cc>
Date: Mon Sep 28 22:35:41 2015 -0300
Add rotate-on-center operation
Rotate a given buffer, translating to its center first. After
rotation, calculate the amount needed to keep the produced extent
on the positive quadrant (always having the origin at its top-left
corner). Then translate that amount. Everything is done with
an unique affine matrix.
Because always translate to center, both origin-x and origin-y
parameters are ignored. Their descriptions are changed to inform
about that.
Composition test includes a crop step to make it sure we have
origin at top-left.
operations/transform/Makefile.am | 1 +
operations/transform/module.c | 2 +
operations/transform/rotate-on-center.c | 128 +++++++++++++++++++++
tests/compositions/Makefile.am | 1 +
tests/compositions/reference/rotate-on-center.png | Bin 0 -> 308940 bytes
tests/compositions/rotate-on-center.xml | 24 ++++
6 files changed, 156 insertions(+), 0 deletions(-)
---
diff --git a/operations/transform/Makefile.am b/operations/transform/Makefile.am
index 30d8f1e..41fd0ee 100644
--- a/operations/transform/Makefile.am
+++ b/operations/transform/Makefile.am
@@ -13,6 +13,7 @@ transformops_la_SOURCES = \
module.h \
reflect.c \
rotate.c \
+ rotate-on-center.c \
scale-ratio.c \
scale-size.c \
scale-size-keepaspect.c \
diff --git a/operations/transform/module.c b/operations/transform/module.c
index 5148dfa..6210d80 100644
--- a/operations/transform/module.c
+++ b/operations/transform/module.c
@@ -40,6 +40,7 @@ gegl_module_query (GTypeModule *module)
}
GType rotate_get_type (void);
+GType rotate_on_center_get_type (void);
GType scale_ratio_get_type (void);
GType scale_size_get_type (void);
GType scale_size_keepaspect_get_type (void);
@@ -56,6 +57,7 @@ gegl_module_register (GTypeModule *module)
dummy = op_transform_get_type ();
dummy = rotate_get_type ();
+ dummy = rotate_on_center_get_type ();
dummy = scale_ratio_get_type ();
dummy = scale_size_get_type ();
dummy = scale_size_keepaspect_get_type ();
diff --git a/operations/transform/rotate-on-center.c b/operations/transform/rotate-on-center.c
new file mode 100644
index 0000000..0dd7360
--- /dev/null
+++ b/operations/transform/rotate-on-center.c
@@ -0,0 +1,128 @@
+/* This file is part of 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 2014 Jon Nordby, The Grid <jononor gmail com>
+ * Copyright 2015 Vilson Vieira, The Grid <vilson void cc>
+ */
+
+#include "config.h"
+#include <glib/gi18n-lib.h>
+
+#ifdef GEGL_CHANT_PROPERTIES
+
+gegl_chant_double (degrees, -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+ _("Angle to rotate (clockwise)"))
+/*
+ * Override the original properties' descriptions, informing they are ignored
+ * and always set to buffer's center coordinates.
+ */
+gegl_chant_double (origin_x, -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+ _("Ignored. Always uses center of input buffer"))
+gegl_chant_double (origin_y, -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+ _("Ignored. Always uses center of input buffer"))
+
+#else
+
+#define GEGL_CHANT_NAME rotate_on_center
+#define GEGL_CHANT_OPERATION_NAME "gegl:rotate-on-center"
+#define GEGL_CHANT_DESCRIPTION _("Rotate the buffer around its center, taking care of possible offsets.")
+#define GEGL_CHANT_SELF "rotate-on-center.c"
+#include "chant.h"
+
+#include <math.h>
+
+static void
+generate_matrix (GeglMatrix3 *matrix,
+ gdouble degrees,
+ gdouble x,
+ gdouble y,
+ gdouble width,
+ gdouble height)
+{
+ gint i;
+ gdouble radians = degrees * (2 * G_PI / 360.0),
+ tx = 0.0,
+ ty = 0.0,
+ tcoords[4][2];
+ /*
+ * Find coordinates of each corner of the bounding box around buffer,
+ * after the requested rotation.
+ */
+ tcoords[0][0] = - x*cos (radians) - y*sin (radians);
+ tcoords[0][1] = x*sin (radians) - y*cos (radians);
+
+ tcoords[1][0] = width*cos (radians) + tcoords[0][0];
+ tcoords[1][1] = - width*sin (radians) + tcoords[0][1];
+
+ tcoords[2][0] = width*cos (radians) + height*sin (radians) + tcoords[0][0];
+ tcoords[2][1] = - width*sin (radians) + height*cos (radians) + tcoords[0][1];
+
+ tcoords[3][0] = height*sin (radians) + tcoords[0][0];
+ tcoords[3][1] = height*cos (radians) + tcoords[0][1];
+
+ /*
+ * Find translation needed to make the bounding box stays in the positive
+ * quadrant.
+ */
+ for (i=0; i<G_N_ELEMENTS (tcoords); i++) {
+ tx = MIN (tx, tcoords[i][0]);
+ ty = MIN (ty, tcoords[i][1]);
+ }
+
+ /*
+ * Define an affine matrix that:
+ * 1. Translates buffer's center to origin
+ * 2. Rotates buffer by given degrees
+ * 3. Translates to the positive quadrant
+ */
+ matrix->coeff [0][0] = cos (radians);
+ matrix->coeff [0][1] = sin (radians);
+ matrix->coeff [0][2] = -tx - x*cos (radians) - y*sin (radians);
+
+ matrix->coeff [1][0] = -sin (radians);
+ matrix->coeff [1][1] = cos (radians);
+ matrix->coeff [1][2] = -ty + x*sin (radians) - y*cos (radians);
+
+ matrix->coeff [2][0] = 0;
+ matrix->coeff [2][1] = 0;
+ matrix->coeff [2][2] = 1;
+}
+
+static void
+create_matrix (OpTransform *op,
+ GeglMatrix3 *matrix)
+{
+ GeglChantOperation *chant = GEGL_CHANT_OPERATION (op);
+ GeglOperation *operation = GEGL_OPERATION (op);
+ GeglRectangle in_rect = {0.0,0.0,0.0,0.0};
+
+ if (gegl_operation_source_get_bounding_box (operation, "input"))
+ in_rect = *gegl_operation_source_get_bounding_box (operation, "input");
+
+ // Avoid divide-by-zero
+ if (in_rect.width < 1)
+ in_rect.width = 1;
+ if (in_rect.height < 1)
+ in_rect.height = 1;
+
+ generate_matrix (matrix,
+ chant->degrees,
+ in_rect.width,
+ in_rect.height,
+ in_rect.width,
+ in_rect.height);
+}
+
+#endif
diff --git a/tests/compositions/Makefile.am b/tests/compositions/Makefile.am
index cdfa07c..c2d9de4 100644
--- a/tests/compositions/Makefile.am
+++ b/tests/compositions/Makefile.am
@@ -53,6 +53,7 @@ TESTS = \
reinhard05.xml \
rgb-params.xml \
rotate.xml \
+ rotate-on-center.xml \
simple-scale.xml \
scale-size-keepaspect.xml \
sinus.xml \
diff --git a/tests/compositions/reference/rotate-on-center.png
b/tests/compositions/reference/rotate-on-center.png
new file mode 100644
index 0000000..2bc8633
Binary files /dev/null and b/tests/compositions/reference/rotate-on-center.png differ
diff --git a/tests/compositions/rotate-on-center.xml b/tests/compositions/rotate-on-center.xml
new file mode 100644
index 0000000..3a725ec
--- /dev/null
+++ b/tests/compositions/rotate-on-center.xml
@@ -0,0 +1,24 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<gegl>
+ <node operation='gegl:crop'>
+ <params>
+ <param name='x'>0</param>
+ <param name='y'>0</param>
+ <param name='width'>280</param>
+ <param name='height'>270</param>
+ </params>
+ </node>
+ <node operation='gegl:rotate-on-center'>
+ <params>
+ <param name='degrees'>45.8</param>
+ <param name='sampler'>linear</param>
+ <param name='origin-x'>0</param>
+ <param name='origin-y'>0</param>
+ </params>
+ </node>
+ <node operation='gegl:load'>
+ <params>
+ <param name="path">data/duck.png</param>
+ </params>
+ </node>
+</gegl>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]