gegl r2868 - in trunk: . gegl/buffer
- From: ok svn gnome org
- To: svn-commits-list gnome org
- Subject: gegl r2868 - in trunk: . gegl/buffer
- Date: Wed, 14 Jan 2009 12:15:58 +0000 (UTC)
Author: ok
Date: Wed Jan 14 12:15:58 2009
New Revision: 2868
URL: http://svn.gnome.org/viewvc/gegl?rev=2868&view=rev
Log:
Applied patch from Nicolas Robidoux that adds a new sampler
(gegl-sampler-sharp) building on the existing YAFR resamplers.
* gegl/buffer/Makefile.am:
* gegl/buffer/gegl-buffer-access.c:
* gegl/buffer/gegl-buffer.c:
* gegl/buffer/gegl-buffer.h:
* gegl/buffer/gegl-sampler-linear.c: (gegl_sampler_linear_init),
(gegl_sampler_linear_get), (set_property), (get_property):
* gegl/buffer/gegl-sampler-yafr.c: (gegl_sampler_yafr_init),
(catrom_yafr), (gegl_sampler_yafr_get):
* gegl/buffer/gegl-sampler.c:
(gegl_buffer_interpolation_from_string),
(gegl_sampler_type_from_interpolation):
Modified:
trunk/ChangeLog
trunk/gegl/buffer/Makefile.am
trunk/gegl/buffer/gegl-buffer-access.c
trunk/gegl/buffer/gegl-buffer.c
trunk/gegl/buffer/gegl-buffer.h
trunk/gegl/buffer/gegl-sampler-linear.c
trunk/gegl/buffer/gegl-sampler-yafr.c
trunk/gegl/buffer/gegl-sampler.c
Modified: trunk/gegl/buffer/Makefile.am
==============================================================================
--- trunk/gegl/buffer/Makefile.am (original)
+++ trunk/gegl/buffer/Makefile.am Wed Jan 14 12:15:58 2009
@@ -22,6 +22,7 @@
gegl-sampler-lanczos.c \
gegl-sampler-linear.c \
gegl-sampler-nearest.c \
+ gegl-sampler-sharp.c \
gegl-sampler-yafr.c \
gegl-region-generic.c \
gegl-tile.c \
@@ -51,6 +52,7 @@
gegl-sampler-lanczos.h \
gegl-sampler-linear.h \
gegl-sampler-nearest.h \
+ gegl-sampler-sharp.h \
gegl-sampler-yafr.h \
gegl-region.h \
gegl-region-generic.h \
Modified: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-access.c (original)
+++ trunk/gegl/buffer/gegl-buffer-access.c Wed Jan 14 12:15:58 2009
@@ -36,6 +36,7 @@
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
#include "gegl-sampler-lanczos.h"
+#include "gegl-sampler-sharp.h"
#include "gegl-sampler-yafr.h"
#include "gegl-buffer-index.h"
#include "gegl-tile-backend.h"
Modified: trunk/gegl/buffer/gegl-buffer.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.c (original)
+++ trunk/gegl/buffer/gegl-buffer.c Wed Jan 14 12:15:58 2009
@@ -62,6 +62,7 @@
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
#include "gegl-sampler-lanczos.h"
+#include "gegl-sampler-sharp.h"
#include "gegl-sampler-yafr.h"
#include "gegl-types.h"
#include "gegl-utils.h"
Modified: trunk/gegl/buffer/gegl-buffer.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.h (original)
+++ trunk/gegl/buffer/gegl-buffer.h Wed Jan 14 12:15:58 2009
@@ -295,6 +295,7 @@
GEGL_INTERPOLATION_LINEAR,
GEGL_INTERPOLATION_CUBIC,
GEGL_INTERPOLATION_LANCZOS,
+ GEGL_INTERPOLATION_SHARP,
GEGL_INTERPOLATION_YAFR
} GeglInterpolation;
Modified: trunk/gegl/buffer/gegl-sampler-linear.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-linear.c (original)
+++ trunk/gegl/buffer/gegl-sampler-linear.c Wed Jan 14 12:15:58 2009
@@ -1,20 +1,62 @@
/* 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.
+ * 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/>.
+ * License along with GEGL; if not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+/*
+ * FAST_PSEUDO_FLOOR is a floor and floorf replacement which has been
+ * found to be faster on several linux boxes than the library
+ * version. It returns the floor of its argument unless the argument
+ * is a negative integer, in which case it returns one less than the
+ * floor. For example:
+ *
+ * FAST_PSEUDO_FLOOR(0.5) = 0
+ *
+ * FAST_PSEUDO_FLOOR(0.f) = 0
+ *
+ * FAST_PSEUDO_FLOOR(-.5) = -1
+ *
+ * as expected, but
+ *
+ * FAST_PSEUDO_FLOOR(-1.f) = -2
*
+ * The locations of the discontinuities of FAST_PSEUDO_FLOOR are the
+ * same as floor and floorf; it is just that at negative integers the
+ * function is discontinuous on the right instead of the left.
+ */
+#define FAST_PSEUDO_FLOOR(x) ( (int)(x) - ( (x) < 0. ) )
+/*
+ * Alternative (if conditional move is fast and correctly identified
+ * by the compiler):
+ *
+ * #define FAST_PSEUDO_FLOOR(x) ( (x)>=0 ? (int)(x) : (int)(x)-1 )
*/
+#ifndef restrict
+#ifdef __restrict
+#define restrict __restrict
+#else
+#ifdef __restrict__
+#define restrict __restrict__
+#else
+#define restrict
+#endif
+#endif
+#endif
#include <glib-object.h>
#include <glib/gstdio.h>
@@ -22,9 +64,6 @@
#include "gegl-types.h"
#include "gegl-buffer-private.h"
#include "gegl-sampler-linear.h"
-#include <string.h>
-#include <math.h>
-
enum
{
@@ -32,19 +71,20 @@
PROP_LAST
};
-static void gegl_sampler_linear_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
-static void set_property (GObject *gobject,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void get_property (GObject *gobject,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
+static void gegl_sampler_linear_get ( GeglSampler* restrict self,
+ const gdouble x,
+ const gdouble y,
+ void* restrict output);
+
+static void set_property (GObject* gobject,
+ guint property_id,
+ GValue* value,
+ GParamSpec* pspec);
+
+static void get_property (GObject* gobject,
+ guint property_id,
+ GValue* value,
+ GParamSpec* pspec);
G_DEFINE_TYPE (GeglSamplerLinear, gegl_sampler_linear, GEGL_TYPE_SAMPLER)
@@ -57,89 +97,154 @@
object_class->set_property = set_property;
object_class->get_property = get_property;
- sampler_class->get = gegl_sampler_linear_get;
+ sampler_class->get = gegl_sampler_linear_get;
}
static void
gegl_sampler_linear_init (GeglSamplerLinear *self)
{
- GEGL_SAMPLER (self)->context_rect = (GeglRectangle){ 0, 0, 2, 2};
+ GEGL_SAMPLER (self)->context_rect = (GeglRectangle){ 0, 0, 2, 2 };
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
-void
-gegl_sampler_linear_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output)
-{
- gfloat *sampler_bptr;
- const gint offsets[4]={0, 4,
- (64-1)*4, 4};
- gfloat newval[4] = {0.0, 0.0, 0.0, 0.0};
- gfloat q[4];
- gfloat dx,dy;
- gfloat uf, vf;
- gint u,v;
- gint i;
-
-
- uf = x - (gint) x;
- vf = y - (gint) y;
-
- q[0] = (1 - uf) * (1 - vf);
- q[1] = uf * (1 - vf);
- q[2] = (1 - uf) * vf;
- q[3] = uf * vf;
- dx = (gint) x;
- dy = (gint) y;
-
- sampler_bptr = gegl_sampler_get_ptr (self, dx, dy);
-
- /* FIXME: unroll this loop */
- for (i=0, v=dy; v < dy+2; v++)
- for (u=dx; u < dx+2; u++, i++)
- {
- sampler_bptr += offsets[i];
- newval[0] += q[i] * sampler_bptr[0];
- newval[1] += q[i] * sampler_bptr[1];
- newval[2] += q[i] * sampler_bptr[2];
- newval[3] += q[i] * sampler_bptr[3];
- }
+static void
+gegl_sampler_linear_get ( GeglSampler* restrict self,
+ const gdouble absolute_x,
+ const gdouble absolute_y,
+ void* restrict output)
+{
+ const gint pixels_per_buffer_row = 64;
+ const gint channels = 4;
+
+ /*
+ * floor's surrogate FAST_PSEUDO_FLOOR is used to make
+ * sure that the transition through 0 is smooth. If it is known that
+ * negative absolute_x and absolute_y will never be used, plain
+ * cast---that is, const gint ix = absolute_x---is recommended
+ * instead.
+ */
+ const gint ix = FAST_PSEUDO_FLOOR (absolute_x);
+ const gint iy = FAST_PSEUDO_FLOOR (absolute_y);
+
+ /*
+ * x is the x-coordinate of the sampling point relative to the
+ * position of the top left pixel center. Similarly for y. Range of
+ * values: [0,1].
+ */
+ const gfloat x = absolute_x - ix;
+ const gfloat y = absolute_y - iy;
+
+ /*
+ * Point the data tile pointer to the first channel of the top_left
+ * pixel value:
+ */
+ const gfloat* restrict in_bptr = gegl_sampler_get_ptr (self, ix, iy);
+
+ /*
+ * First bilinear weight:
+ */
+ const gfloat x_times_y = x * y;
+
+ /*
+ * Load top row:
+ */
+ const gfloat top_left_0 = *in_bptr++;
+ const gfloat top_left_1 = *in_bptr++;
+ const gfloat top_left_2 = *in_bptr++;
+ const gfloat top_left_3 = *in_bptr++;
+ const gfloat top_rite_0 = *in_bptr++;
+ const gfloat top_rite_1 = *in_bptr++;
+ const gfloat top_rite_2 = *in_bptr++;
+ const gfloat top_rite_3 = *in_bptr;
+
+ in_bptr += 1 + ( pixels_per_buffer_row - 2 ) * channels;
+
+ {
+ /*
+ * More bilinear weights:
+ *
+ * (Note: w = 1-x and z = 1-y.)
+ */
+ const gfloat w_times_y = y - x_times_y;
+ const gfloat x_times_z = x - x_times_y;
+
+ /*
+ * Load bottom row:
+ */
+ const gfloat bot_left_0 = *in_bptr++;
+ const gfloat bot_left_1 = *in_bptr++;
+ const gfloat bot_left_2 = *in_bptr++;
+ const gfloat bot_left_3 = *in_bptr++;
+ const gfloat bot_rite_0 = *in_bptr++;
+ const gfloat bot_rite_1 = *in_bptr++;
+ const gfloat bot_rite_2 = *in_bptr++;
+ const gfloat bot_rite_3 = *in_bptr;
+
+ /*
+ * Last bilinear weight:
+ */
+ const gfloat w_times_z = 1.f - ( x + w_times_y );
+
+ gfloat newval[4];
+
+ newval[0] =
+ x_times_y * bot_rite_0
+ +
+ w_times_y * bot_left_0
+ +
+ x_times_z * top_rite_0
+ +
+ w_times_z * top_left_0;
+
+ newval[1] =
+ x_times_y * bot_rite_1
+ +
+ w_times_y * bot_left_1
+ +
+ x_times_z * top_rite_1
+ +
+ w_times_z * top_left_1;
+
+ newval[2] =
+ x_times_y * bot_rite_2
+ +
+ w_times_y * bot_left_2
+ +
+ x_times_z * top_rite_2
+ +
+ w_times_z * top_left_2;
+
+ newval[3] =
+ x_times_y * bot_rite_3
+ +
+ w_times_y * bot_left_3
+ +
+ x_times_z * top_rite_3
+ +
+ w_times_z * top_left_3;
babl_process (babl_fish (self->interpolate_format, self->format),
- newval, output, 1);
+ newval,
+ output,
+ 1);
+ }
}
-
-
static void
-set_property (GObject *gobject,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- switch (property_id)
- {
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
- break;
- }
+set_property (GObject* gobject,
+ guint property_id,
+ GValue* value,
+ GParamSpec* pspec)
+{
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
}
static void
-get_property (GObject *gobject,
+get_property (GObject* gobject,
guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ GValue* value,
+ GParamSpec* pspec)
{
- switch (property_id)
- {
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
- break;
- }
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
}
Modified: trunk/gegl/buffer/gegl-sampler-yafr.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-yafr.c (original)
+++ trunk/gegl/buffer/gegl-sampler-yafr.c Wed Jan 14 12:15:58 2009
@@ -16,6 +16,10 @@
*
* 2008 (c) Nicolas Robidoux (developer of Yet Another Fast
* Resampler).
+ *
+ * Acknowledgement: N. Robidoux's research on YAFR funded in part by
+ * an NSERC (National Science and Engineering Research Council of
+ * Canada) Discovery Grant.
*/
#include <glib-object.h>
@@ -23,40 +27,7 @@
#include "gegl-buffer-private.h"
#include "gegl-sampler-yafr.h"
-/*
- * This source code contains two versions of Catmull-Rom YAFR:
- *
- * One is for actual use in gegl.
- *
- * The other one is there to show what implementing a better abyss
- * policy (either inside or outside of the samplers) or passing to the
- * samplers information about where the valid data starts and ends,
- * could do. Uncomment the following #define and recompile to
- * activate this demo version.
- *
- * Once installed, you can quickly see the difference by typing gegl
- * in a terminal.
- *
- * Then, on the default "GEGL banner image", try shear with origin-x =
- * 590, origin-y = -200, x (shear coefficient) = 0.1, y (shear
- * coefficient) = -.2, and toggle the various samplers.
- *
- * Or try rotation by 7 degrees with origin-x = 150 and origin-y =
- * 150.
- *
- * The demo version makes the incorrect assumption that the "real"
- * data starts at index 0, which may or may not hold. Also, it does
- * not use information regarding where the real data ends because,
- * despite helpful hints from Geert Jordaens, I have not figured out
- * how to make the sampler access this information.
- *
- */
-
-/* #define ___DEMO_OF_YAFR_WITH_CAREFUL_BOUNDARY_CONDITIONS___ */
-
-#ifndef ___DEMO_OF_YAFR_WITH_CAREFUL_BOUNDARY_CONDITIONS___
#include <math.h>
-#endif
#ifndef restrict
#ifdef __restrict
@@ -70,13 +41,7 @@
#endif
#endif
-#ifndef unlikely
-#ifdef __builtin_expect
-#define unlikely(x) __builtin_expect((x),0)
-#else
-#define unlikely(x) (x)
-#endif
-#endif
+#define FAST_PSEUDO_FLOOR(x) ( (int)(x) - ( (x) < 0. ) )
enum
{
@@ -105,39 +70,45 @@
* YAFR = Yet Another Fast Resampler
*
* Yet Another Fast Resampler is a nonlinear resampler which consists
- * of Catmull-Rom (which is a linear scheme) plus a nonlinear
- * sharpening correction which is tuned for the straightening of
+ * of a linear scheme (in this version, Catmull-Rom) plus a nonlinear
+ * sharpening correction the purpose of which is the straightening of
* diagonal interfaces between flat colour areas.
*
* Key properties:
*
- * YAFR is interpolatory:
+ * YAFR (smooth) is interpolatory:
*
* If asked for the value at the center of an input pixel, it will
* return the corresponding value, unchanged.
*
- * YAFR preserves local averages:
+ * YAFR (smooth) preserves local averages:
*
* The average of the reconstructed intensity surface over any region
* is the same as the average of the piecewise constant surface with
* values over pixel areas equal to the input pixel values (the
* "nearest neighbour" surface), except for a small amount of blur at
- * the boundary of the region. More precicely: YAFR is a box filtered
- * exact area method.
+ * the boundary of the region. More precicely: YAFR (smooth) is a box
+ * filtered exact area method.
*
- * Main weakness of YAFR:
+ * Main weaknesses of YAFR (smooth):
*
- * Executive summary: YAFR improves on Catmull-Rom only for images
+ * Weakness 1: YAFR (smooth) improves on Catmull-Rom only for images
* with at least a little bit of smoothness.
*
- * More specifically: If a portion of the image is such that every
- * pixel has immediate neighbours in the horizontal and vertical
- * directions which have exactly the same pixel value, then YAFR boils
- * down to Catmull-Rom, and the computation of the correction is a
- * waste. Extreme case: If all the pixels are either pure black or
- * pure white in some region, as in some text images (more generally,
- * if the region is "bichromatic"), then the correction is 0 in the
- * interior of the bichromatic region.
+ * Weakness 2: Catmull-Rom introduces a lot of haloing. YAFR (smooth)
+ * is based on Catmull-Rom, and consequently it too introduces a lot
+ * of haloing.
+ *
+ * More details regarding Weakness 1:
+ *
+ * If a portion of the image is such that every pixel has immediate
+ * neighbours in the horizontal and vertical directions which have
+ * exactly the same pixel value, then YAFR (smooth) boils down to
+ * Catmull-Rom, and the computation of the correction is a waste.
+ * Extreme case: If all the pixels are either pure black or pure white
+ * in some region, as in some text images (more generally, if the
+ * region is "bichromatic"), then the YAFR (smooth) correction is 0 in
+ * the interior of the bichromatic region.
*/
static void
@@ -155,12 +126,15 @@
static void
gegl_sampler_yafr_init (GeglSamplerYafr *self)
{
+ /*
+ * The computation stencil is 4x4, and sticks out one column to the
+ * left and one row above the requested integer position:
+ */
GEGL_SAMPLER (self)->context_rect = (GeglRectangle){-1,-1,4,4};
+
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
-#ifndef ___DEMO_OF_YAFR_WITH_CAREFUL_BOUNDARY_CONDITIONS___
-
static inline gfloat
catrom_yafr (const gfloat cardinal_one,
const gfloat cardinal_two,
@@ -174,383 +148,109 @@
const gfloat left_width_times_dow_height_times_rite_width,
const gfloat left_width_times_up__height_times_dow_height,
const gfloat rite_width_times_up__height_times_dow_height,
- const gfloat* restrict this_channels_one_uno_bptr)
+ const gfloat* restrict this_channels_uno_one_bptr)
{
- const gfloat sharpening_over_two = 0.453125f;
/*
* "sharpening" is a continuous method parameter which is
* proportional to the amount of "diagonal straightening" which the
- * nonlinear correction part of the method may add. You may also
- * think of it as a sharpening parameter: higher values correspond
- * to more sharpening, negative values to strange looking effects.
- *
- * The default value is sharpening = 29/32. When the scheme being
- * "straightened" is Catmull-Rom---as is the case here---this value
- * fixes key pixel values near a diagonal boundary between two
+ * nonlinear correction part of the method may add to the underlying
+ * linear scheme. You may also think of it as a sharpening
+ * parameter: higher values correspond to more sharpening, and
+ * negative values lead to strange looking effects.
+ *
+ * The default value is sharpening = 29/32 when the scheme being
+ * "straightened" is Catmull-Rom---as is the case here. This value
+ * fixes key pixel values near the diagonal boundary between two
* monochrome regions (the diagonal boundary pixel values being set
* to the halfway colour).
*
* If resampling seems to add unwanted texture artifacts, push
- * sharpening toward 0. It is not recommended to set sharpening to a
- * value larger than 4.
+ * sharpening toward 0. It is not generally not recommended to set
+ * sharpening to a value larger than 4.
*
- * We scale sharpening by half because the .5 which has to do with
- * the relative coordinates of the evaluation points (which has to
- * do with .5*rite_width etc) is folded into the constant to save
- * flops.
+ * Sharpening is halved because the .5 which has to do with the
+ * relative coordinates of the evaluation points (which has to do
+ * with .5*rite_width etc) is folded into the constant to save
+ * flops. Consequently, the largest recommended value of
+ * sharpening_over_two is 2=4/2.
+ *
+ * In order to simplify interfacing with users, the parameter which
+ * should be set by the user is normalized so that user_sharpening =
+ * 1 when sharpening is equal to the recommended value. Consistently
+ * with the above discussion, values of user_sharpening between 0
+ * and about 3.625 give good results.
*/
+ const gfloat user_sharpening = 1.f;
+ const gfloat sharpening_over_two = user_sharpening * 0.453125f;
/*
- * Load the useful pixel values for the channel under
- * consideration. The pointer is assumed to point to one_uno.
- */
- const gint channels = 4;
- const gint pixels_per_row = 64;
- /*
* The input pixel values are described by the following stencil.
- * English abbreviations are used to label positions from left to
- * right, Spanish ones to label positions from top to bottom:
- *
- * (dx-1,dy-1) (dx,dy-1) (dx+1,dy-1) (dx+2,dy-1)
- * =one_uno =two_uno =thr_uno = fou_uno
+ * Spanish abbreviations are used to label positions from top to
+ * bottom, English ones to label positions from left to right,:
*
- * (dx-1,dy) (dx,dy) (dx+1,dy) (dx+2,dy)
- * =one_dos =two_dos =thr_dos = fou_dos
+ * (ix-1,iy-1) (ix,iy-1) (ix+1,iy-1) (ix+2,iy-1)
+ * =uno_one =uno_two =uno_thr = uno_fou
*
- * (dx-1,dy+1) (dx,dy+1) (dx+1,dy+1) (dx+2,dy+1)
- * =one_tre =two_tre =thr_tre = fou_tre
- *
- * (dx-1,dy+2) (dx,dy+2) (dx+1,dy+2) (dx+2,dy+2)
- * =one_qua =two_qua =thr_qua = fou_qua
- */
- const gfloat one_uno =
- this_channels_one_uno_bptr[ 0 ];
- const gfloat two_uno =
- this_channels_one_uno_bptr[ channels ];
- const gfloat thr_uno =
- this_channels_one_uno_bptr[ 2*channels ];
- const gfloat fou_uno =
- this_channels_one_uno_bptr[ 3*channels ];
-
- const gfloat one_dos =
- this_channels_one_uno_bptr[ pixels_per_row*channels ];
- const gfloat two_dos =
- this_channels_one_uno_bptr[ channels + pixels_per_row*channels ];
- const gfloat thr_dos =
- this_channels_one_uno_bptr[ 2*channels + pixels_per_row*channels ];
- const gfloat fou_dos =
- this_channels_one_uno_bptr[ 3*channels + pixels_per_row*channels ];
-
- const gfloat one_tre =
- this_channels_one_uno_bptr[ 2*pixels_per_row*channels ];
- const gfloat two_tre =
- this_channels_one_uno_bptr[ channels + 2*pixels_per_row*channels ];
- const gfloat thr_tre =
- this_channels_one_uno_bptr[ 2*channels + 2*pixels_per_row*channels ];
- const gfloat fou_tre =
- this_channels_one_uno_bptr[ 3*channels + 2*pixels_per_row*channels ];
-
- const gfloat one_qua =
- this_channels_one_uno_bptr[ 3*pixels_per_row*channels ];
- const gfloat two_qua =
- this_channels_one_uno_bptr[ channels + 3*pixels_per_row*channels ];
- const gfloat thr_qua =
- this_channels_one_uno_bptr[ 2*channels + 3*pixels_per_row*channels ];
- const gfloat fou_qua =
- this_channels_one_uno_bptr[ 3*channels + 3*pixels_per_row*channels ];
-
- /*
- * Computation of the YAFR correction:
+ * (ix-1,iy) (ix,iy) (ix+1,iy) (ix+2,iy)
+ * =dos_one =dos_two =dos_thr = dos_fou
*
- * Basically, if two consecutive pixel value differences have the
- * same sign, the smallest one (in absolute value) is taken to be
- * the corresponding slope. Otherwise, the corresponding slope is
- * set to 0.
+ * (ix-1,iy+1) (ix,iy+1) (ix+1,iy+1) (ix+2,iy+1)
+ * =tre_one =tre_two =tre_thr = tre_fou
*
- * Four such pairs (vertical and horizontal) of slopes need to be
- * computed, one pair for each of the pixels which potentially
- * overlap the unit area centered at the interpolation point.
- */
- /*
- * Beginning of the computation of the "up" horizontal slopes:
- */
- const gfloat prem__up = two_dos - one_dos;
- const gfloat deux__up = thr_dos - two_dos;
- const gfloat troi__up = fou_dos - thr_dos;
- /*
- * "down" horizontal slopes:
- */
- const gfloat prem_dow = two_tre - one_tre;
- const gfloat deux_dow = thr_tre - two_tre;
- const gfloat troi_dow = fou_tre - thr_tre;
- /*
- * "left" vertical slopes:
- */
- const gfloat prem_left = two_dos - two_uno;
- const gfloat deux_left = two_tre - two_dos;
- const gfloat troi_left = two_qua - two_tre;
- /*
- * "right" vertical slopes:
- */
- const gfloat prem_rite = thr_dos - thr_uno;
- const gfloat deux_rite = thr_tre - thr_dos;
- const gfloat troi_rite = thr_qua - thr_tre;
-
- /*
- * Branching parts of the computation of the YAFR correction (could
- * be unbranched using C99 math intrinsics, or by the compiler):
- */
- /*
- * Back to "up":
- */
- const gfloat abs_prem__up = prem__up < 0.f ? -prem__up : prem__up;
- const gfloat abs_deux__up = deux__up < 0.f ? -deux__up : deux__up;
- const gfloat abs_troi__up = troi__up < 0.f ? -troi__up : troi__up;
- /*
- * Back to "down":
- */
- const gfloat abs_prem_dow = prem_dow < 0.f ? -prem_dow : prem_dow;
- const gfloat abs_deux_dow = deux_dow < 0.f ? -deux_dow : deux_dow;
- const gfloat abs_troi_dow = troi_dow < 0.f ? -troi_dow : troi_dow;
- /*
- * Back to "left":
- */
- const gfloat abs_prem_left = prem_left < 0.f ? -prem_left : prem_left;
- const gfloat abs_deux_left = deux_left < 0.f ? -deux_left : deux_left;
- const gfloat abs_troi_left = troi_left < 0.f ? -troi_left : troi_left;
- /*
- * Back to "right":
- */
- const gfloat abs_prem_rite = prem_rite < 0.f ? -prem_rite : prem_rite;
- const gfloat abs_deux_rite = deux_rite < 0.f ? -deux_rite : deux_rite;
- const gfloat abs_troi_rite = troi_rite < 0.f ? -troi_rite : troi_rite;
-
- /*
- * "up":
- */
- const gfloat prem__up_times_deux__up = prem__up * deux__up;
- const gfloat deux__up_times_troi__up = deux__up * troi__up;
- /*
- * "down":
- */
- const gfloat prem_dow_times_deux_dow = prem_dow * deux_dow;
- const gfloat deux_dow_times_troi_dow = deux_dow * troi_dow;
- /*
- * "left":
- */
- const gfloat prem_left_times_deux_left = prem_left * deux_left;
- const gfloat deux_left_times_troi_left = deux_left * troi_left;
- /*
- * "right":
- */
- const gfloat prem_rite_times_deux_rite = prem_rite * deux_rite;
- const gfloat deux_rite_times_troi_rite = deux_rite * troi_rite;
-
- /*
- * "up":
- */
- const gfloat prem__up_vs_deux__up =
- abs_prem__up < abs_deux__up ? prem__up : deux__up;
- const gfloat deux__up_vs_troi__up =
- abs_deux__up < abs_troi__up ? deux__up : troi__up;
- /*
- * "down":
- */
- const gfloat prem_dow_vs_deux_dow =
- abs_prem_dow < abs_deux_dow ? prem_dow : deux_dow;
- const gfloat deux_dow_vs_troi_dow =
- abs_deux_dow < abs_troi_dow ? deux_dow : troi_dow;
- /*
- * "left":
- */
- const gfloat prem_left_vs_deux_left =
- abs_prem_left < abs_deux_left ? prem_left : deux_left;
- const gfloat deux_left_vs_troi_left =
- abs_deux_left < abs_troi_left ? deux_left : troi_left;
- /*
- * "right":
- */
- const gfloat prem_rite_vs_deux_rite =
- abs_prem_rite < abs_deux_rite ? prem_rite : deux_rite;
- const gfloat deux_rite_vs_troi_rite =
- abs_deux_rite < abs_troi_rite ? deux_rite : troi_rite;
- /*
- * The YAFR correction computation will resume after the computation
- * of the Catmull-Rom baseline.
- */
-
- /*
- * Catmull-Rom baseline contribution:
- */
- const gfloat catmull_rom =
- cardinal_uno *
- (
- cardinal_one * one_uno
- +
- cardinal_two * two_uno
- +
- cardinal_thr * thr_uno
- +
- cardinal_fou * fou_uno
- )
- +
- cardinal_dos *
- (
- cardinal_one * one_dos
- +
- cardinal_two * two_dos
- +
- cardinal_thr * thr_dos
- +
- cardinal_fou * fou_dos
- )
- +
- cardinal_tre *
- (
- cardinal_one * one_tre
- +
- cardinal_two * two_tre
- +
- cardinal_thr * thr_tre
- +
- cardinal_fou * fou_tre
- )
- +
- cardinal_qua *
- (
- cardinal_one * one_qua
- +
- cardinal_two * two_qua
- +
- cardinal_thr * thr_qua
- +
- cardinal_fou * fou_qua
- );
-
- /*
- * Computation of the YAFR slopes.
- */
- /*
- * "up":
- */
- const gfloat mx_left__up =
- prem__up_times_deux__up < 0.f ? 0.f : prem__up_vs_deux__up;
- const gfloat mx_rite__up =
- deux__up_times_troi__up < 0.f ? 0.f : deux__up_vs_troi__up;
- /*
- * "down":
- */
- const gfloat mx_left_dow =
- prem_dow_times_deux_dow < 0.f ? 0.f : prem_dow_vs_deux_dow;
- const gfloat mx_rite_dow =
- deux_dow_times_troi_dow < 0.f ? 0.f : deux_dow_vs_troi_dow;
- /*
- * "left":
- */
- const gfloat my_left__up =
- prem_left_times_deux_left < 0.f ? 0.f : prem_left_vs_deux_left;
- const gfloat my_left_dow =
- deux_left_times_troi_left < 0.f ? 0.f : deux_left_vs_troi_left;
- /*
- * "down":
- */
- const gfloat my_rite__up =
- prem_rite_times_deux_rite < 0.f ? 0.f : prem_rite_vs_deux_rite;
- const gfloat my_rite_dow =
- deux_rite_times_troi_rite < 0.f ? 0.f : deux_rite_vs_troi_rite;
-
- /*
- * Assemble the YAFR correction:
- */
- const gfloat unweighted_yafr_correction =
- left_width_times_up__height_times_rite_width
- *
- ( mx_left__up - mx_rite__up )
- +
- left_width_times_dow_height_times_rite_width
- *
- ( mx_left_dow - mx_rite_dow )
- +
- left_width_times_up__height_times_dow_height
- *
- ( my_left__up - my_left_dow )
- +
- rite_width_times_up__height_times_dow_height
- *
- ( my_rite__up - my_rite_dow );
-
- /*
- * Add the Catmull-Rom baseline and the weighted YAFR correction:
+ * (ix-1,iy+2) (ix,iy+2) (ix+1,iy+2) (ix+2,iy+2)
+ * =qua_one =qua_two =qua_thr = qua_fou
*/
- const gfloat newval =
- sharpening_over_two * unweighted_yafr_correction + catmull_rom;
- return newval;
-}
-
-#else
-
-static inline gfloat
-catrom_yafr (const gfloat cardinal_one,
- const gfloat cardinal_two,
- const gfloat cardinal_thr,
- const gfloat cardinal_fou,
- const gfloat cardinal_uno,
- const gfloat cardinal_dos,
- const gfloat cardinal_tre,
- const gfloat cardinal_qua,
- const gfloat left_width_times_up__height_times_rite_width,
- const gfloat left_width_times_dow_height_times_rite_width,
- const gfloat left_width_times_up__height_times_dow_height,
- const gfloat rite_width_times_up__height_times_dow_height,
- const gfloat one_uno,
- const gfloat two_uno,
- const gfloat thr_uno,
- const gfloat fou_uno,
- const gfloat one_dos,
- const gfloat two_dos,
- const gfloat thr_dos,
- const gfloat fou_dos,
- const gfloat one_tre,
- const gfloat two_tre,
- const gfloat thr_tre,
- const gfloat fou_tre,
- const gfloat one_qua,
- const gfloat two_qua,
- const gfloat thr_qua,
- const gfloat fou_qua)
-{
- const gfloat sharpening_over_two = 0.453125f;
/*
- * "sharpening" is a continuous method parameter which is
- * proportional to the amount of "diagonal straightening" which the
- * nonlinear correction part of the method may add. You may also
- * think of it as a sharpening parameter: higher values correspond
- * to more sharpening, negative values to strange looking effects.
- *
- * The default value is sharpening = 29/32. When the scheme being
- * "straightened" is Catmull-Rom---as is the case here---this value
- * fixes key pixel values near a diagonal boundary between two
- * monochrome regions (the diagonal boundary pixel values being set
- * to the halfway colour).
- *
- * If resampling seems to add unwanted texture artifacts, push
- * sharpening toward 0. It is not recommended to set sharpening to a
- * value larger than 4.
- *
- * We scale sharpening by half because the .5 which has to do with
- * the relative coordinates of the evaluation points (which has to
- * do with .5*rite_width etc) is folded into the constant to save
- * flops.
+ * Load the useful pixel values for the channel under
+ * consideration. The this_channels_uno_one_bptr pointer is assumed
+ * to point to uno_one when catrom_yafr is entered.
*/
+ const gint channels = 4;
+ const gint pixels_per_buffer_row = 64;
+ const gfloat uno_one =
+ this_channels_uno_one_bptr[ 0 ];
+ const gfloat uno_two =
+ this_channels_uno_one_bptr[ channels ];
+ const gfloat uno_thr =
+ this_channels_uno_one_bptr[ 2 * channels ];
+ const gfloat uno_fou =
+ this_channels_uno_one_bptr[ 3 * channels ];
+
+ const gfloat dos_one =
+ this_channels_uno_one_bptr[ pixels_per_buffer_row * channels ];
+ const gfloat dos_two =
+ this_channels_uno_one_bptr[ ( 1 + pixels_per_buffer_row ) * channels ];
+ const gfloat dos_thr =
+ this_channels_uno_one_bptr[ ( 2 + pixels_per_buffer_row ) * channels ];
+ const gfloat dos_fou =
+ this_channels_uno_one_bptr[ ( 3 + pixels_per_buffer_row ) * channels ];
+
+ const gfloat tre_one =
+ this_channels_uno_one_bptr[ 2 * pixels_per_buffer_row * channels ];
+ const gfloat tre_two =
+ this_channels_uno_one_bptr[ ( 1 + 2 * pixels_per_buffer_row ) * channels ];
+ const gfloat tre_thr =
+ this_channels_uno_one_bptr[ ( 2 + 2 * pixels_per_buffer_row ) * channels ];
+ const gfloat tre_fou =
+ this_channels_uno_one_bptr[ ( 3 + 2 * pixels_per_buffer_row ) * channels ];
+
+ const gfloat qua_one =
+ this_channels_uno_one_bptr[ 3 * pixels_per_buffer_row * channels ];
+ const gfloat qua_two =
+ this_channels_uno_one_bptr[ ( 1 + 3 * pixels_per_buffer_row ) * channels ];
+ const gfloat qua_thr =
+ this_channels_uno_one_bptr[ ( 2 + 3 * pixels_per_buffer_row ) * channels ];
+ const gfloat qua_fou =
+ this_channels_uno_one_bptr[ ( 3 + 3 * pixels_per_buffer_row ) * channels ];
/*
* Computation of the YAFR correction:
*
* Basically, if two consecutive pixel value differences have the
* same sign, the smallest one (in absolute value) is taken to be
- * the corresponding slope. Otherwise, the corresponding slope is
- * set to 0.
+ * the corresponding slope. If they don't have the same sign, the
+ * corresponding slope is set to 0.
*
* Four such pairs (vertical and horizontal) of slopes need to be
* computed, one pair for each of the pixels which potentially
@@ -559,56 +259,52 @@
/*
* Beginning of the computation of the "up" horizontal slopes:
*/
- const gfloat prem__up = two_dos - one_dos;
- const gfloat deux__up = thr_dos - two_dos;
- const gfloat troi__up = fou_dos - thr_dos;
+ const gfloat prem__up = dos_two - dos_one;
+ const gfloat deux__up = dos_thr - dos_two;
+ const gfloat troi__up = dos_fou - dos_thr;
/*
* "down" horizontal slopes:
*/
- const gfloat prem_dow = two_tre - one_tre;
- const gfloat deux_dow = thr_tre - two_tre;
- const gfloat troi_dow = fou_tre - thr_tre;
+ const gfloat prem_dow = tre_two - tre_one;
+ const gfloat deux_dow = tre_thr - tre_two;
+ const gfloat troi_dow = tre_fou - tre_thr;
/*
* "left" vertical slopes:
*/
- const gfloat prem_left = two_dos - two_uno;
- const gfloat deux_left = two_tre - two_dos;
- const gfloat troi_left = two_qua - two_tre;
+ const gfloat prem_left = dos_two - uno_two;
+ const gfloat deux_left = tre_two - dos_two;
+ const gfloat troi_left = qua_two - tre_two;
/*
* "right" vertical slopes:
*/
- const gfloat prem_rite = thr_dos - thr_uno;
- const gfloat deux_rite = thr_tre - thr_dos;
- const gfloat troi_rite = thr_qua - thr_tre;
+ const gfloat prem_rite = dos_thr - uno_thr;
+ const gfloat deux_rite = tre_thr - dos_thr;
+ const gfloat troi_rite = qua_thr - tre_thr;
/*
- * Branching parts of the computation of the YAFR correction (could
- * be unbranched using C99 math intrinsics, or by the compiler):
- */
- /*
* Back to "up":
*/
- const gfloat abs_prem__up = prem__up < 0.f ? -prem__up : prem__up;
- const gfloat abs_deux__up = deux__up < 0.f ? -deux__up : deux__up;
- const gfloat abs_troi__up = troi__up < 0.f ? -troi__up : troi__up;
+ const gfloat prem__up_squared = prem__up * prem__up;
+ const gfloat deux__up_squared = deux__up * deux__up;
+ const gfloat troi__up_squared = troi__up * troi__up;
/*
* Back to "down":
*/
- const gfloat abs_prem_dow = prem_dow < 0.f ? -prem_dow : prem_dow;
- const gfloat abs_deux_dow = deux_dow < 0.f ? -deux_dow : deux_dow;
- const gfloat abs_troi_dow = troi_dow < 0.f ? -troi_dow : troi_dow;
+ const gfloat prem_dow_squared = prem_dow * prem_dow;
+ const gfloat deux_dow_squared = deux_dow * deux_dow;
+ const gfloat troi_dow_squared = troi_dow * troi_dow;
/*
* Back to "left":
*/
- const gfloat abs_prem_left = prem_left < 0.f ? -prem_left : prem_left;
- const gfloat abs_deux_left = deux_left < 0.f ? -deux_left : deux_left;
- const gfloat abs_troi_left = troi_left < 0.f ? -troi_left : troi_left;
+ const gfloat prem_left_squared = prem_left * prem_left;
+ const gfloat deux_left_squared = deux_left * deux_left;
+ const gfloat troi_left_squared = troi_left * troi_left;
/*
* Back to "right":
*/
- const gfloat abs_prem_rite = prem_rite < 0.f ? -prem_rite : prem_rite;
- const gfloat abs_deux_rite = deux_rite < 0.f ? -deux_rite : deux_rite;
- const gfloat abs_troi_rite = troi_rite < 0.f ? -troi_rite : troi_rite;
+ const gfloat prem_rite_squared = prem_rite * prem_rite;
+ const gfloat deux_rite_squared = deux_rite * deux_rite;
+ const gfloat troi_rite_squared = troi_rite * troi_rite;
/*
* "up":
@@ -632,33 +328,39 @@
const gfloat deux_rite_times_troi_rite = deux_rite * troi_rite;
/*
+ * Branching parts of the computation of the YAFR correction (could
+ * be unbranched using arithmetic branching and C99 math intrinsics,
+ * although the compiler may be smart enough to remove the branching
+ * on its own):
+ */
+ /*
* "up":
*/
const gfloat prem__up_vs_deux__up =
- abs_prem__up < abs_deux__up ? prem__up : deux__up;
+ prem__up_squared < deux__up_squared ? prem__up : deux__up;
const gfloat deux__up_vs_troi__up =
- abs_deux__up < abs_troi__up ? deux__up : troi__up;
+ deux__up_squared < troi__up_squared ? deux__up : troi__up;
/*
* "down":
*/
const gfloat prem_dow_vs_deux_dow =
- abs_prem_dow < abs_deux_dow ? prem_dow : deux_dow;
+ prem_dow_squared < deux_dow_squared ? prem_dow : deux_dow;
const gfloat deux_dow_vs_troi_dow =
- abs_deux_dow < abs_troi_dow ? deux_dow : troi_dow;
+ deux_dow_squared < troi_dow_squared ? deux_dow : troi_dow;
/*
* "left":
*/
const gfloat prem_left_vs_deux_left =
- abs_prem_left < abs_deux_left ? prem_left : deux_left;
+ prem_left_squared < deux_left_squared ? prem_left : deux_left;
const gfloat deux_left_vs_troi_left =
- abs_deux_left < abs_troi_left ? deux_left : troi_left;
+ deux_left_squared < troi_left_squared ? deux_left : troi_left;
/*
* "right":
*/
const gfloat prem_rite_vs_deux_rite =
- abs_prem_rite < abs_deux_rite ? prem_rite : deux_rite;
+ prem_rite_squared < deux_rite_squared ? prem_rite : deux_rite;
const gfloat deux_rite_vs_troi_rite =
- abs_deux_rite < abs_troi_rite ? deux_rite : troi_rite;
+ deux_rite_squared < troi_rite_squared ? deux_rite : troi_rite;
/*
* The YAFR correction computation will resume after the computation
* of the Catmull-Rom baseline.
@@ -670,46 +372,46 @@
const gfloat catmull_rom =
cardinal_uno *
(
- cardinal_one * one_uno
+ cardinal_one * uno_one
+
- cardinal_two * two_uno
+ cardinal_two * uno_two
+
- cardinal_thr * thr_uno
+ cardinal_thr * uno_thr
+
- cardinal_fou * fou_uno
+ cardinal_fou * uno_fou
)
+
cardinal_dos *
(
- cardinal_one * one_dos
+ cardinal_one * dos_one
+
- cardinal_two * two_dos
+ cardinal_two * dos_two
+
- cardinal_thr * thr_dos
+ cardinal_thr * dos_thr
+
- cardinal_fou * fou_dos
+ cardinal_fou * dos_fou
)
+
cardinal_tre *
(
- cardinal_one * one_tre
+ cardinal_one * tre_one
+
- cardinal_two * two_tre
+ cardinal_two * tre_two
+
- cardinal_thr * thr_tre
+ cardinal_thr * tre_thr
+
- cardinal_fou * fou_tre
+ cardinal_fou * tre_fou
)
+
cardinal_qua *
(
- cardinal_one * one_qua
+ cardinal_one * qua_one
+
- cardinal_two * two_qua
+ cardinal_two * qua_two
+
- cardinal_thr * thr_qua
+ cardinal_thr * qua_thr
+
- cardinal_fou * fou_qua
+ cardinal_fou * qua_fou
);
/*
@@ -745,7 +447,7 @@
deux_rite_times_troi_rite < 0.f ? 0.f : deux_rite_vs_troi_rite;
/*
- * Assemble the YAFR correction:
+ * Assemble the unweighted YAFR correction:
*/
const gfloat unweighted_yafr_correction =
left_width_times_up__height_times_rite_width
@@ -773,10 +475,6 @@
return newval;
}
-#endif
-
-#ifndef ___DEMO_OF_YAFR_WITH_CAREFUL_BOUNDARY_CONDITIONS___
-
static void
gegl_sampler_yafr_get ( GeglSampler *self,
const gdouble x,
@@ -784,25 +482,26 @@
void *output)
{
/*
- * The computation is structured to foster software pipelining.
+ * Note: The computation is structured to foster software
+ * pipelining.
*/
/*
- * x is understood to increase from left to right (like the index
- * "j"), y, from top to bottom (like the index "i"). Consequently,
- * dx and dy are the indices of the pixel located at or to the left,
- * and at or above. the sampling point.
- */
- /* floor is used to make sure that the transition through 0 is
- * smooth:
+ * x is understood to increase from left to right, y, from top to
+ * bottom. Consequently, ix and iy are the indices of the pixel
+ * located at or to the left, and at or above. the sampling point.
+ *
+ * floor is used to make sure that the transition through 0 is
+ * smooth. If it is known that negative x and y will never be used,
+ * cast (which truncates) could be used instead.
*/
- const gint dx = floorf (x);
- const gint dy = floorf (y);
+ const gint ix = FAST_PSEUDO_FLOOR (x);
+ const gint iy = FAST_PSEUDO_FLOOR (y);
/*
* Pointer to enlarged input stencil values:
*/
- const gfloat* restrict sampler_bptr = gegl_sampler_get_ptr (self, dx, dy);
+ const gfloat* restrict sampler_bptr = gegl_sampler_get_ptr (self, ix, iy);
/*
* Each (channel's) output pixel value is obtained by combining four
@@ -810,12 +509,12 @@
* closest to the four pixels closest to the (x,y) position, pixel
* positions which have coordinates and labels as follows:
*
- * (dx,dy) (dx+1,dy)
+ * (ix,iy) (ix+1,iy)
* =left__up =rite__up
*
* <- (x,y) is somewhere in the convex hull
*
- * (dx,dy+1) (dx+1,dy+1)
+ * (ix,iy+1) (ix+1,iy+1)
* =left_dow =rite_dow
*/
/*
@@ -827,8 +526,8 @@
* (which is centered at the position where an interpolated value is
* desired), with the closest unit pixel areas to the left.
*/
- const gfloat rite_width = x - dx;
- const gfloat dow_height = y - dy;
+ const gfloat rite_width = x - ix;
+ const gfloat dow_height = y - iy;
const gfloat left_width = 1.f - rite_width;
const gfloat up__height = 1.f - dow_height;
/*
@@ -846,12 +545,6 @@
* -.5*up__height is the y-coordinate ... down pixel areas, relative
* to ... the down pixels.
*/
-
- /*
- * Values of the Catmull-Rom cardinal basis functions at the
- * sampling point. Recyclable quantities are computed at the same
- * time:
- */
const gfloat left_width_times_rite_width = left_width * rite_width;
const gfloat up__height_times_dow_height = up__height * dow_height;
@@ -878,11 +571,11 @@
const gfloat cardinal_one =
minus_half_left_width_times_rite_width * left_width;
- const gfloat cardinal_fou =
- minus_half_left_width_times_rite_width * rite_width;
-
const gfloat cardinal_uno =
minus_half_up__height_times_dow_height * up__height;
+
+ const gfloat cardinal_fou =
+ minus_half_left_width_times_rite_width * rite_width;
const gfloat cardinal_qua =
minus_half_up__height_times_dow_height * dow_height;
@@ -898,11 +591,13 @@
gfloat newval[4];
/*
- * Set the tile pointer to the first relevant value:
+ * Set the tile pointer to the first relevant value. Since the
+ * pointer initially points to dos_two, we need to rewind it one
+ * tile row, then go back one additional pixel.
*/
const gint channels = 4;
- const gint pixels_per_row = 64;
- sampler_bptr -= channels + pixels_per_row * channels;
+ const gint pixels_per_buffer_row = 64;
+ sampler_bptr -= ( pixels_per_buffer_row + 1 ) * channels;
newval[0] = catrom_yafr (cardinal_one,
cardinal_two,
@@ -966,360 +661,6 @@
1);
}
-#else
-
-void
-gegl_sampler_yafr_get ( GeglSampler *self,
- const gdouble x,
- const gdouble y,
- void *output)
-{
- /*
- * The input pixel values are described by the following stencil.
- * English abbreviations are used to label positions from left to
- * right, Spanish ones to label positions from top to bottom:
- *
- * (dx-1,dy-1) (dx,dy-1) (dx+1,dy-1) (dx+2,dy-1)
- * =one_uno =two_uno =thr_uno = fou_uno
- *
- * (dx-1,dy) (dx,dy) (dx+1,dy) (dx+2,dy)
- * =one_dos =two_dos =thr_dos = fou_dos
- *
- * (dx-1,dy+1) (dx,dy+1) (dx+1,dy+1) (dx+2,dy+1)
- * =one_tre =two_tre =thr_tre = fou_tre
- *
- * (dx-1,dy+2) (dx,dy+2) (dx+1,dy+2) (dx+2,dy+2)
- * =one_qua =two_qua =thr_qua = fou_qua
- *
- * They are further differentiated by channel ("_0," ,,, "_3").
- */
- gfloat one_uno_0, one_uno_1, one_uno_2, one_uno_3;
- gfloat two_uno_0, two_uno_1, two_uno_2, two_uno_3;
- gfloat thr_uno_0, thr_uno_1, thr_uno_2, thr_uno_3;
- gfloat fou_uno_0, fou_uno_1, fou_uno_2, fou_uno_3;
- gfloat one_dos_0, one_dos_1, one_dos_2, one_dos_3;
- gfloat two_dos_0, two_dos_1, two_dos_2, two_dos_3;
- gfloat thr_dos_0, thr_dos_1, thr_dos_2, thr_dos_3;
- gfloat fou_dos_0, fou_dos_1, fou_dos_2, fou_dos_3;
- gfloat one_tre_0, one_tre_1, one_tre_2, one_tre_3;
- gfloat two_tre_0, two_tre_1, two_tre_2, two_tre_3;
- gfloat thr_tre_0, thr_tre_1, thr_tre_2, thr_tre_3;
- gfloat fou_tre_0, fou_tre_1, fou_tre_2, fou_tre_3;
- gfloat one_qua_0, one_qua_1, one_qua_2, one_qua_3;
- gfloat two_qua_0, two_qua_1, two_qua_2, two_qua_3;
- gfloat thr_qua_0, thr_qua_1, thr_qua_2, thr_qua_3;
- gfloat fou_qua_0, fou_qua_1, fou_qua_2, fou_qua_3;
- /*
- * Each (channel's) output pixel value is obtained by combining four
- * "pieces," each piece corresponding to the set of points which are
- * closest to the four pixels closest to the (x,y) position, pixel
- * positions which have coordinates and labels as follows:
- *
- * (dx,dy) (dx+1,dy)
- * =left__up =rite__up
- *
- * <- (x,y) is somewhere in the convex hull
- *
- * (dx,dy+1) (dx+1,dy+1)
- * =left_dow =rite_dow
- *
- * See the first comment of the catrom_yafr function for the
- * corresponding "input values" picture.
- */
- /*
- * x is understood to increase from left to right (like the index
- * "j"), y, from top to bottom (like the index "i"). If the sampling
- * position is outside the image extent, replace it by the closest
- * one on the boundary of the image:
- */
- const gfloat local_x = x < 0.f ? 0.f : x;
- const gfloat local_y = y < 0.f ? 0.f : y;
- /*
- * dx and dy are the positions of the pixel which is at or to the
- * left, and at or above, the sampling position:
- */
- const gint dx = (gint) local_x;
- const gint dy = (gint) local_y;
- /*
- * Pointer to enlarged input stencil with 64x64(x4) entries pointing
- * to the leftmost/uppermost (one_uno for channel 0) value in the
- * 4x4(x4) stencil:
- */
- gfloat* restrict sampler_bptr = gegl_sampler_get_ptr (self, dx, dy);
-
- /*
- * Set the tile pointer to the first relevant value:
- */
- const gint channels = 4;
- const gint pixels_per_row = 64;
- const gint stencil_width = 4;
- sampler_bptr -= channels + pixels_per_row * channels;
-
- one_uno_0 = *sampler_bptr++;
- one_uno_1 = *sampler_bptr++;
- one_uno_2 = *sampler_bptr++;
- one_uno_3 = *sampler_bptr++;
- two_uno_0 = *sampler_bptr++;
- two_uno_1 = *sampler_bptr++;
- two_uno_2 = *sampler_bptr++;
- two_uno_3 = *sampler_bptr++;
- thr_uno_0 = *sampler_bptr++;
- thr_uno_1 = *sampler_bptr++;
- thr_uno_2 = *sampler_bptr++;
- thr_uno_3 = *sampler_bptr++;
- fou_uno_0 = *sampler_bptr++;
- fou_uno_1 = *sampler_bptr++;
- fou_uno_2 = *sampler_bptr++;
- fou_uno_3 = *sampler_bptr;
- sampler_bptr += 1 + ( pixels_per_row - stencil_width ) * channels;
- one_dos_0 = *sampler_bptr++;
- one_dos_1 = *sampler_bptr++;
- one_dos_2 = *sampler_bptr++;
- one_dos_3 = *sampler_bptr++;
- two_dos_0 = *sampler_bptr++;
- two_dos_1 = *sampler_bptr++;
- two_dos_2 = *sampler_bptr++;
- two_dos_3 = *sampler_bptr++;
- thr_dos_0 = *sampler_bptr++;
- thr_dos_1 = *sampler_bptr++;
- thr_dos_2 = *sampler_bptr++;
- thr_dos_3 = *sampler_bptr++;
- fou_dos_0 = *sampler_bptr++;
- fou_dos_1 = *sampler_bptr++;
- fou_dos_2 = *sampler_bptr++;
- fou_dos_3 = *sampler_bptr;
- sampler_bptr += 1 + ( pixels_per_row - stencil_width ) * channels;
- one_tre_0 = *sampler_bptr++;
- one_tre_1 = *sampler_bptr++;
- one_tre_2 = *sampler_bptr++;
- one_tre_3 = *sampler_bptr++;
- two_tre_0 = *sampler_bptr++;
- two_tre_1 = *sampler_bptr++;
- two_tre_2 = *sampler_bptr++;
- two_tre_3 = *sampler_bptr++;
- thr_tre_0 = *sampler_bptr++;
- thr_tre_1 = *sampler_bptr++;
- thr_tre_2 = *sampler_bptr++;
- thr_tre_3 = *sampler_bptr++;
- fou_tre_0 = *sampler_bptr++;
- fou_tre_1 = *sampler_bptr++;
- fou_tre_2 = *sampler_bptr++;
- fou_tre_3 = *sampler_bptr;
- sampler_bptr += 1 + ( pixels_per_row - stencil_width ) * channels;
- one_qua_0 = *sampler_bptr++;
- one_qua_1 = *sampler_bptr++;
- one_qua_2 = *sampler_bptr++;
- one_qua_3 = *sampler_bptr++;
- two_qua_0 = *sampler_bptr++;
- two_qua_1 = *sampler_bptr++;
- two_qua_2 = *sampler_bptr++;
- two_qua_3 = *sampler_bptr++;
- thr_qua_0 = *sampler_bptr++;
- thr_qua_1 = *sampler_bptr++;
- thr_qua_2 = *sampler_bptr++;
- thr_qua_3 = *sampler_bptr++;
- fou_qua_0 = *sampler_bptr++;
- fou_qua_1 = *sampler_bptr++;
- fou_qua_2 = *sampler_bptr++;
- fou_qua_3 = *sampler_bptr;
- /*
- * If the stencil sticks out to the left---and consequently was
- * filled with values computed with the default abyss
- * policy)---replace the corresponding "made up" (abyss) values by
- * values computed using (bi)yafr extrapolation:
- */
- if unlikely (dx == (gint) 0)
- {
- one_uno_0 = 2.f * two_uno_0 - thr_uno_0;
- one_uno_1 = 2.f * two_uno_1 - thr_uno_1;
- one_uno_2 = 2.f * two_uno_2 - thr_uno_2;
- one_uno_3 = 2.f * two_uno_3 - thr_uno_3;
- one_dos_0 = 2.f * two_dos_0 - thr_dos_0;
- one_dos_1 = 2.f * two_dos_1 - thr_dos_1;
- one_dos_2 = 2.f * two_dos_2 - thr_dos_2;
- one_dos_3 = 2.f * two_dos_3 - thr_dos_3;
- one_tre_0 = 2.f * two_tre_0 - thr_tre_0;
- one_tre_1 = 2.f * two_tre_1 - thr_tre_1;
- one_tre_2 = 2.f * two_tre_2 - thr_tre_2;
- one_tre_3 = 2.f * two_tre_3 - thr_tre_3;
- one_qua_0 = 2.f * two_qua_0 - thr_qua_0;
- one_qua_1 = 2.f * two_qua_1 - thr_qua_1;
- one_qua_2 = 2.f * two_qua_2 - thr_qua_2;
- one_qua_3 = 2.f * two_qua_3 - thr_qua_3;
- }
- /*
- * Same if the stencil sticks out of the top:
- */
- if unlikely (dy == (gint) 0)
- {
- one_uno_0 = 2.f * one_dos_0 - one_tre_0;
- one_uno_1 = 2.f * one_dos_1 - one_tre_1;
- one_uno_2 = 2.f * one_dos_2 - one_tre_2;
- one_uno_3 = 2.f * one_dos_3 - one_tre_3;
- two_uno_0 = 2.f * two_dos_0 - two_tre_0;
- two_uno_1 = 2.f * two_dos_1 - two_tre_1;
- two_uno_2 = 2.f * two_dos_2 - two_tre_2;
- two_uno_3 = 2.f * two_dos_3 - two_tre_3;
- thr_uno_0 = 2.f * thr_dos_0 - thr_tre_0;
- thr_uno_1 = 2.f * thr_dos_1 - thr_tre_1;
- thr_uno_2 = 2.f * thr_dos_2 - thr_tre_2;
- thr_uno_3 = 2.f * thr_dos_3 - thr_tre_3;
- fou_uno_0 = 2.f * fou_dos_0 - fou_tre_0;
- fou_uno_1 = 2.f * fou_dos_1 - fou_tre_1;
- fou_uno_2 = 2.f * fou_dos_2 - fou_tre_2;
- fou_uno_3 = 2.f * fou_dos_3 - fou_tre_3;
- }
-
- {
- /*
- * Each (channel's) output pixel value is obtained by combining
- * four "pieces," each piece corresponding to the set of points
- * which are closest to the four pixels closest to the (x,y)
- * position, pixel positions which have coordinates and labels as
- * follows:
- *
- * (dx,dy) (dx+1,dy)
- * =left__up =rite__up
- *
- * <- (x,y) is somewhere in the convex hull
- *
- * (dx,dy+1) (dx+1,dy+1)
- * =left_dow =rite_dow
- */
- /*
- * rite_width is the width of the overlaps of the unit averaging
- * box (which is centered at the position where an interpolated
- * value is desired), with the closest unit pixel areas to the
- * right.
- *
- * left_width is the width of the overlaps of the unit averaging
- * box (which is centered at the position where an interpolated
- * value is desired), with the closest unit pixel areas to the
- * left.
- */
- const gfloat rite_width = x - dx;
- const gfloat dow_height = y - dy;
- const gfloat left_width = 1.f - rite_width;
- const gfloat up__height = 1.f - dow_height;
- /*
- * .5*rite_width is the x-coordinate of the center of the overlap of
- * the averaging box with the left pixel areas, relative to the
- * position of the centers of the left pixels.
- *
- * -.5*left_width is the x-coordinate ... right pixel areas,
- * relative to ... the right pixels.
- *
- * .5*dow_height is the y-coordinate of the center of the overlap
- * of the averaging box with the up pixel areas, relative to the
- * position of the centers of the up pixels.
- *
- * -.5*up__height is the y-coordinate ... down pixel areas,
- * relative to ... the down pixels.
- */
-
- /*
- * Values of the Catmull-Rom cardinal basis functions at the
- * sampling point. Recyclable quantities are computed at the same
- * time:
- */
- const gfloat left_width_times_rite_width = left_width * rite_width;
- const gfloat up__height_times_dow_height = up__height * dow_height;
-
- const gfloat cardinal_two =
- left_width_times_rite_width * ( -1.5f * rite_width + 1.f )
- + left_width;
- const gfloat cardinal_dos =
- up__height_times_dow_height * ( -1.5f * dow_height + 1.f )
- + up__height;
-
- const gfloat minus_half_left_width_times_rite_width =
- -.5f * left_width_times_rite_width;
- const gfloat minus_half_up__height_times_dow_height =
- -.5f * up__height_times_dow_height;
-
- const gfloat left_width_times_up__height_times_rite_width =
- left_width_times_rite_width * up__height;
- const gfloat left_width_times_dow_height_times_rite_width =
- left_width_times_rite_width * dow_height;
- const gfloat left_width_times_up__height_times_dow_height =
- up__height_times_dow_height * left_width;
- const gfloat rite_width_times_up__height_times_dow_height =
- up__height_times_dow_height * rite_width;
-
- const gfloat cardinal_one =
- minus_half_left_width_times_rite_width * left_width;
- const gfloat cardinal_fou =
- minus_half_left_width_times_rite_width * rite_width;
-
- const gfloat cardinal_uno =
- minus_half_up__height_times_dow_height * up__height;
- const gfloat cardinal_qua =
- minus_half_up__height_times_dow_height * dow_height;
-
- const gfloat cardinal_thr =
- 1.f - ( minus_half_left_width_times_rite_width + cardinal_two );
- const gfloat cardinal_tre =
- 1.f - ( minus_half_up__height_times_dow_height + cardinal_dos );
-
- gfloat newval[4];
-
- newval[0] =
- catrom_yafr (cardinal_one, cardinal_two, cardinal_thr, cardinal_fou,
- cardinal_uno, cardinal_dos, cardinal_tre, cardinal_qua,
- left_width_times_up__height_times_rite_width,
- left_width_times_dow_height_times_rite_width,
- left_width_times_up__height_times_dow_height,
- rite_width_times_up__height_times_dow_height,
- one_uno_0, two_uno_0, thr_uno_0, fou_uno_0,
- one_dos_0, two_dos_0, thr_dos_0, fou_dos_0,
- one_tre_0, two_tre_0, thr_tre_0, fou_tre_0,
- one_qua_0, two_qua_0, thr_qua_0, fou_qua_0);
- newval[1] =
- catrom_yafr (cardinal_one, cardinal_two, cardinal_thr, cardinal_fou,
- cardinal_uno, cardinal_dos, cardinal_tre, cardinal_qua,
- left_width_times_up__height_times_rite_width,
- left_width_times_dow_height_times_rite_width,
- left_width_times_up__height_times_dow_height,
- rite_width_times_up__height_times_dow_height,
- one_uno_1, two_uno_1, thr_uno_1, fou_uno_1,
- one_dos_1, two_dos_1, thr_dos_1, fou_dos_1,
- one_tre_1, two_tre_1, thr_tre_1, fou_tre_1,
- one_qua_1, two_qua_1, thr_qua_1, fou_qua_1);
- newval[2] =
- catrom_yafr (cardinal_one, cardinal_two, cardinal_thr, cardinal_fou,
- cardinal_uno, cardinal_dos, cardinal_tre, cardinal_qua,
- left_width_times_up__height_times_rite_width,
- left_width_times_dow_height_times_rite_width,
- left_width_times_up__height_times_dow_height,
- rite_width_times_up__height_times_dow_height,
- one_uno_2, two_uno_2, thr_uno_2, fou_uno_2,
- one_dos_2, two_dos_2, thr_dos_2, fou_dos_2,
- one_tre_2, two_tre_2, thr_tre_2, fou_tre_2,
- one_qua_2, two_qua_2, thr_qua_2, fou_qua_2);
- newval[3] =
- catrom_yafr (cardinal_one, cardinal_two, cardinal_thr, cardinal_fou,
- cardinal_uno, cardinal_dos, cardinal_tre, cardinal_qua,
- left_width_times_up__height_times_rite_width,
- left_width_times_dow_height_times_rite_width,
- left_width_times_up__height_times_dow_height,
- rite_width_times_up__height_times_dow_height,
- one_uno_3, two_uno_3, thr_uno_3, fou_uno_3,
- one_dos_3, two_dos_3, thr_dos_3, fou_dos_3,
- one_tre_3, two_tre_3, thr_tre_3, fou_tre_3,
- one_qua_3, two_qua_3, thr_qua_3, fou_qua_3);
-
- /*
- * Ship out the new values:
- */
- babl_process (babl_fish (self->interpolate_format, self->format),
- newval,
- output,
- 1);
- }
-}
-
-#endif
-
static void
set_property ( GObject *gobject,
guint property_id,
@@ -1337,3 +678,4 @@
{
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
}
+
Modified: trunk/gegl/buffer/gegl-sampler.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler.c (original)
+++ trunk/gegl/buffer/gegl-sampler.c Wed Jan 14 12:15:58 2009
@@ -30,6 +30,7 @@
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
#include "gegl-sampler-lanczos.h"
+#include "gegl-sampler-sharp.h"
#include "gegl-sampler-yafr.h"
#if ENABLE_MP
@@ -413,6 +414,9 @@
if (g_str_equal (string, "cubic") || g_str_equal (string, "bicubic"))
return GEGL_INTERPOLATION_CUBIC;
+ if (g_str_equal (string, "sharp"))
+ return GEGL_INTERPOLATION_SHARP;
+
if (g_str_equal (string, "yafr"))
return GEGL_INTERPOLATION_YAFR;
@@ -433,6 +437,8 @@
return GEGL_TYPE_SAMPLER_LINEAR;
case GEGL_INTERPOLATION_CUBIC:
return GEGL_TYPE_SAMPLER_CUBIC;
+ case GEGL_INTERPOLATION_SHARP:
+ return GEGL_TYPE_SAMPLER_SHARP;
case GEGL_INTERPOLATION_YAFR:
return GEGL_TYPE_SAMPLER_YAFR;
case GEGL_INTERPOLATION_LANCZOS:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]