[gegl] ripple: some reworking
- From: Simon Budig <simon src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] ripple: some reworking
- Date: Mon, 23 Apr 2018 23:21:24 +0000 (UTC)
commit d5dc307ab54a9d4dbde7cc54f8010512e0fecbbd
Author: Simon Budig <simon budig de>
Date: Tue Apr 24 01:20:00 2018 +0200
ripple: some reworking
- add options for abyss policy, implement real tileable mode
operations/common-gpl3+/ripple.c | 83 ++++++++++++++++++++++++++++++++-----
1 files changed, 71 insertions(+), 12 deletions(-)
---
diff --git a/operations/common-gpl3+/ripple.c b/operations/common-gpl3+/ripple.c
index 45dabe0..b0ffafc 100644
--- a/operations/common-gpl3+/ripple.c
+++ b/operations/common-gpl3+/ripple.c
@@ -13,6 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
+ * Copyright 2018 Simon Budig <simon gimp org>
* Copyright 2011 Michael Muré <batolettre gmail com>
* Copyright 2011 Robert Sasu <sasu robert gmail com>
* Copyright 2011 Hans Lo <hansshulo gmail com>
@@ -51,6 +52,11 @@ property_enum (sampler_type, _("Resampling method"),
property_enum (wave_type, _("Wave type"),
GeglRippleWaveType, gegl_ripple_wave_type, GEGL_RIPPLE_WAVE_TYPE_SINE)
+property_enum (abyss_policy, _("Abyss policy"),
+ GeglAbyssPolicy, gegl_abyss_policy,
+ GEGL_ABYSS_NONE)
+ description (_("How image edges are handled"))
+
property_boolean (tileable, _("Tileable"), FALSE)
description(_("Retain tilebility"))
@@ -92,14 +98,66 @@ process (GeglOperation *operation,
const GeglRectangle *result,
gint level)
{
- GeglProperties *o = GEGL_PROPERTIES (operation);
+ GeglProperties *o = GEGL_PROPERTIES (operation);
GeglSampler *sampler = gegl_buffer_sampler_new_at_level (input,
babl_format ("RGBA float"),
o->sampler_type,
level);
GeglBufferIterator *iter;
+ gdouble angle_rad, period, amplitude, phi;
- GeglAbyssPolicy abyss = o->tileable ? GEGL_ABYSS_LOOP : GEGL_ABYSS_NONE;
+ angle_rad = o->angle / 180.0 * G_PI;
+ period = o->period;
+ amplitude = o->amplitude;
+ phi = o->phi;
+
+ if (period < 0.0001)
+ {
+ period = 1.0;
+ amplitude = 0.0;
+ }
+
+ if (o->tileable)
+ {
+ gint w, h;
+ gdouble n, m;
+
+ w = gegl_buffer_get_width (input);
+ h = gegl_buffer_get_height (input);
+
+ n = cos (angle_rad) * w / period;
+ m = sin (angle_rad) * h / period;
+
+ /* round away from zero but ensure a nonzero result */
+ n = n < 0 ? MIN (round (n), -1.0) : MAX (round (n), 1.0);
+ m = m < 0 ? MIN (round (m), -1.0) : MAX (round (m), 1.0);
+
+ /* magic! */
+ angle_rad = atan2 (m * w, h * n);
+ period = cos (angle_rad) * w / n;
+
+ /* ok, not actually.
+ *
+ * For the result of the ripple op being tileable you need
+ * to have the period/angle select in a way, so that the top left
+ * corner has an integer * period distance along the angle to
+ * the top right corner as well as the bottom left corner.
+ *
+ * I.e.:
+ *
+ * cos (angle) * width = n * period
+ * sin (angle) * height = m * period
+ *
+ * with n, m being integers.
+ *
+ * We determine n, m by rounding the results optained by the
+ * user specified angle/period and then calculate a hopefully only
+ * slightly modified new angle/period that meets these criteria.
+ *
+ * We determine the angle by computing tan(), thereby eliminating
+ * the period, then determining the period.
+ */
+ }
iter = gegl_buffer_iterator_new (output, result, 0, babl_format ("RGBA float"),
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE);
@@ -118,26 +176,27 @@ process (GeglOperation *operation,
gdouble coordsy;
gdouble lambda;
- gdouble angle_rad = o->angle / 180.0 * G_PI;
gdouble nx = x * cos (angle_rad) - y * sin (angle_rad);
switch (o->wave_type)
{
case GEGL_RIPPLE_WAVE_TYPE_SAWTOOTH:
- lambda = div (nx + o->period / 2, o->period).rem - o->phi * o->period;
+ lambda = div (nx + period / 2, period).rem - phi * period;
if (lambda < 0)
- lambda += o->period;
- shift = o->amplitude * (((lambda / o->period) * 2) - 1);
+ lambda += period;
+ shift = amplitude * (((lambda / period) * 2) - 1);
break;
+
case GEGL_RIPPLE_WAVE_TYPE_TRIANGLE:
- lambda = div (nx + o->period * 3 / 4, o->period).rem - o->phi * o->period;
+ lambda = div (nx + period * 3 / 4, period).rem - phi * period;
if (lambda < 0)
- lambda += o->period;
- shift = o->amplitude * (fabs (((lambda / o->period) * 4) - 2) - 1);
+ lambda += period;
+ shift = amplitude * (fabs (((lambda / period) * 4) - 2) - 1);
break;
+
case GEGL_RIPPLE_WAVE_TYPE_SINE:
default:
- shift = o->amplitude * sin (2.0 * G_PI * nx / o->period + 2.0 * G_PI * o->phi);
+ shift = amplitude * sin (2.0 * G_PI * nx / period + 2.0 * G_PI * phi);
break;
}
@@ -149,7 +208,7 @@ process (GeglOperation *operation,
coordsy,
NULL,
out_pixel,
- abyss);
+ o->abyss_policy);
out_pixel += 4;
}
@@ -157,7 +216,7 @@ process (GeglOperation *operation,
g_object_unref (sampler);
- return TRUE;
+ return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]