|
Packit Service |
2781ba |
/* This file is part of GEGL
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* GEGL is free software; you can redistribute it and/or modify it
|
|
Packit Service |
2781ba |
* under the terms of the GNU Lesser General Public License as
|
|
Packit Service |
2781ba |
* published by the Free Software Foundation; either version 3 of the
|
|
Packit Service |
2781ba |
* License, or (at your option) any later version.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* GEGL is distributed in the hope that it will be useful, but WITHOUT
|
|
Packit Service |
2781ba |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
Packit Service |
2781ba |
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
Packit Service |
2781ba |
* Public License for more details.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit Service |
2781ba |
* License along with GEGL; if not, see
|
|
Packit Service |
2781ba |
* <http://www.gnu.org/licenses/>.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* FAST_PSEUDO_FLOOR is a floor and floorf replacement which has been
|
|
Packit Service |
2781ba |
* found to be faster on several linux boxes than the library
|
|
Packit Service |
2781ba |
* version. It returns the floor of its argument unless the argument
|
|
Packit Service |
2781ba |
* is a negative integer, in which case it returns one less than the
|
|
Packit Service |
2781ba |
* floor. For example:
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* FAST_PSEUDO_FLOOR(0.5) = 0
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* FAST_PSEUDO_FLOOR(0.f) = 0
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* FAST_PSEUDO_FLOOR(-.5) = -1
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* as expected, but
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* FAST_PSEUDO_FLOOR(-1.f) = -2
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* The locations of the discontinuities of FAST_PSEUDO_FLOOR are the
|
|
Packit Service |
2781ba |
* same as floor and floorf; it is just that at negative integers the
|
|
Packit Service |
2781ba |
* function is discontinuous on the right instead of the left.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
#define FAST_PSEUDO_FLOOR(x) ( (int)(x) - ( (x) < 0. ) )
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Alternative (if conditional move is fast and correctly identified
|
|
Packit Service |
2781ba |
* by the compiler):
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* #define FAST_PSEUDO_FLOOR(x) ( (x)>=0 ? (int)(x) : (int)(x)-1 )
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "config.h"
|
|
Packit Service |
2781ba |
#include <glib-object.h>
|
|
Packit Service |
2781ba |
#include <glib/gstdio.h>
|
|
Packit Service |
2781ba |
#include <glib/gprintf.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl.h"
|
|
Packit Service |
2781ba |
#include "gegl-types-internal.h"
|
|
Packit Service |
2781ba |
#include "gegl-buffer-private.h"
|
|
Packit Service |
2781ba |
#include "gegl-sampler-linear.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
enum
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
PROP_0,
|
|
Packit Service |
2781ba |
PROP_LAST
|
|
Packit Service |
2781ba |
};
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void gegl_sampler_linear_get (GeglSampler* restrict self,
|
|
Packit Service |
2781ba |
const gdouble x,
|
|
Packit Service |
2781ba |
const gdouble y,
|
|
Packit Service |
2781ba |
GeglMatrix2 *scale,
|
|
Packit Service |
2781ba |
void* restrict output);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void set_property (GObject* gobject,
|
|
Packit Service |
2781ba |
guint property_id,
|
|
Packit Service |
2781ba |
const GValue* value,
|
|
Packit Service |
2781ba |
GParamSpec* pspec);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void get_property (GObject* gobject,
|
|
Packit Service |
2781ba |
guint property_id,
|
|
Packit Service |
2781ba |
GValue* value,
|
|
Packit Service |
2781ba |
GParamSpec* pspec);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
G_DEFINE_TYPE (GeglSamplerLinear, gegl_sampler_linear, GEGL_TYPE_SAMPLER)
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
gegl_sampler_linear_class_init (GeglSamplerLinearClass *klass)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
|
|
Packit Service |
2781ba |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
object_class->set_property = set_property;
|
|
Packit Service |
2781ba |
object_class->get_property = get_property;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
sampler_class->get = gegl_sampler_linear_get;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
gegl_sampler_linear_init (GeglSamplerLinear *self)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GEGL_SAMPLER (self)->context_rect[0].x = 0;
|
|
Packit Service |
2781ba |
GEGL_SAMPLER (self)->context_rect[0].y = 0;
|
|
Packit Service |
2781ba |
GEGL_SAMPLER (self)->context_rect[0].width = 2;
|
|
Packit Service |
2781ba |
GEGL_SAMPLER (self)->context_rect[0].height = 2;
|
|
Packit Service |
2781ba |
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
gegl_sampler_linear_get (GeglSampler* restrict self,
|
|
Packit Service |
2781ba |
const gdouble absolute_x,
|
|
Packit Service |
2781ba |
const gdouble absolute_y,
|
|
Packit Service |
2781ba |
GeglMatrix2 *scale,
|
|
Packit Service |
2781ba |
void* restrict output)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
const gint pixels_per_buffer_row = 64;
|
|
Packit Service |
2781ba |
const gint channels = 4;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* floor's surrogate FAST_PSEUDO_FLOOR is used to make
|
|
Packit Service |
2781ba |
* sure that the transition through 0 is smooth. If it is known that
|
|
Packit Service |
2781ba |
* negative absolute_x and absolute_y will never be used, plain
|
|
Packit Service |
2781ba |
* cast---that is, const gint ix = absolute_x---is recommended
|
|
Packit Service |
2781ba |
* instead.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gint ix = FAST_PSEUDO_FLOOR (absolute_x);
|
|
Packit Service |
2781ba |
const gint iy = FAST_PSEUDO_FLOOR (absolute_y);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* x is the x-coordinate of the sampling point relative to the
|
|
Packit Service |
2781ba |
* position of the top left pixel center. Similarly for y. Range of
|
|
Packit Service |
2781ba |
* values: [0,1].
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat x = absolute_x - ix;
|
|
Packit Service |
2781ba |
const gfloat y = absolute_y - iy;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Point the data tile pointer to the first channel of the top_left
|
|
Packit Service |
2781ba |
* pixel value:
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat* restrict in_bptr = gegl_sampler_get_ptr (self, ix, iy);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* First bilinear weight:
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat x_times_y = x * y;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Load top row:
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat top_left_0 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_left_1 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_left_2 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_left_3 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_rite_0 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_rite_1 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_rite_2 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat top_rite_3 = *in_bptr;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
in_bptr += 1 + ( pixels_per_buffer_row - 2 ) * channels;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* More bilinear weights:
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* (Note: w = 1-x and z = 1-y.)
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat w_times_y = y - x_times_y;
|
|
Packit Service |
2781ba |
const gfloat x_times_z = x - x_times_y;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Load bottom row:
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat bot_left_0 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_left_1 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_left_2 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_left_3 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_rite_0 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_rite_1 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_rite_2 = *in_bptr++;
|
|
Packit Service |
2781ba |
const gfloat bot_rite_3 = *in_bptr;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Last bilinear weight:
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
const gfloat w_times_z = 1.f - ( x + w_times_y );
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gfloat newval[4];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
newval[0] =
|
|
Packit Service |
2781ba |
x_times_y * bot_rite_0
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_y * bot_left_0
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
x_times_z * top_rite_0
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_z * top_left_0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
newval[1] =
|
|
Packit Service |
2781ba |
x_times_y * bot_rite_1
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_y * bot_left_1
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
x_times_z * top_rite_1
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_z * top_left_1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
newval[2] =
|
|
Packit Service |
2781ba |
x_times_y * bot_rite_2
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_y * bot_left_2
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
x_times_z * top_rite_2
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_z * top_left_2;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
newval[3] =
|
|
Packit Service |
2781ba |
x_times_y * bot_rite_3
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_y * bot_left_3
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
x_times_z * top_rite_3
|
|
Packit Service |
2781ba |
+
|
|
Packit Service |
2781ba |
w_times_z * top_left_3;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
babl_process (self->fish, newval, output, 1);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
set_property (GObject* gobject,
|
|
Packit Service |
2781ba |
guint property_id,
|
|
Packit Service |
2781ba |
const GValue* value,
|
|
Packit Service |
2781ba |
GParamSpec* pspec)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
get_property (GObject* gobject,
|
|
Packit Service |
2781ba |
guint property_id,
|
|
Packit Service |
2781ba |
GValue* value,
|
|
Packit Service |
2781ba |
GParamSpec* pspec)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|