|
Packit |
bc1512 |
/* This file is part of GEGL
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
#include <string.h>
|
|
Packit |
bc1512 |
#include <math.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include <glib-object.h>
|
|
Packit |
bc1512 |
#include <glib/gstdio.h>
|
|
Packit |
bc1512 |
#include <glib/gprintf.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl.h"
|
|
Packit |
bc1512 |
#include "gegl-types-internal.h"
|
|
Packit |
bc1512 |
#include "gegl-buffer-private.h"
|
|
Packit |
bc1512 |
#include "gegl-sampler-cubic.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
enum
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
PROP_0,
|
|
Packit |
bc1512 |
PROP_B,
|
|
Packit |
bc1512 |
PROP_C,
|
|
Packit |
bc1512 |
PROP_TYPE,
|
|
Packit |
bc1512 |
PROP_LAST
|
|
Packit |
bc1512 |
};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void gegl_sampler_cubic_finalize (GObject *gobject);
|
|
Packit |
bc1512 |
static void gegl_sampler_cubic_get (GeglSampler *sampler,
|
|
Packit |
bc1512 |
gdouble x,
|
|
Packit |
bc1512 |
gdouble y,
|
|
Packit |
bc1512 |
GeglMatrix2 *scale,
|
|
Packit |
bc1512 |
void *output);
|
|
Packit |
bc1512 |
static void get_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec);
|
|
Packit |
bc1512 |
static void set_property (GObject *gobject,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
const GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec);
|
|
Packit |
bc1512 |
static inline gfloat cubicKernel (gfloat x,
|
|
Packit |
bc1512 |
gfloat b,
|
|
Packit |
bc1512 |
gfloat c);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
G_DEFINE_TYPE (GeglSamplerCubic, gegl_sampler_cubic, GEGL_TYPE_SAMPLER)
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_sampler_cubic_class_init (GeglSamplerCubicClass *klass)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
|
|
Packit |
bc1512 |
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
object_class->set_property = set_property;
|
|
Packit |
bc1512 |
object_class->get_property = get_property;
|
|
Packit |
bc1512 |
object_class->finalize = gegl_sampler_cubic_finalize;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
sampler_class->get = gegl_sampler_cubic_get;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_class_install_property (object_class, PROP_B,
|
|
Packit |
bc1512 |
g_param_spec_double ("b",
|
|
Packit |
bc1512 |
"B",
|
|
Packit |
bc1512 |
"B-spline parameter",
|
|
Packit |
bc1512 |
0.0,
|
|
Packit |
bc1512 |
1.0,
|
|
Packit |
bc1512 |
1.0,
|
|
Packit |
bc1512 |
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_class_install_property (object_class, PROP_C,
|
|
Packit |
bc1512 |
g_param_spec_double ("c",
|
|
Packit |
bc1512 |
"C",
|
|
Packit |
bc1512 |
"C-spline parameter",
|
|
Packit |
bc1512 |
0.0,
|
|
Packit |
bc1512 |
1.0,
|
|
Packit |
bc1512 |
0.0,
|
|
Packit |
bc1512 |
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_class_install_property (object_class, PROP_TYPE,
|
|
Packit |
bc1512 |
g_param_spec_string ("type",
|
|
Packit |
bc1512 |
"type",
|
|
Packit |
bc1512 |
"B-spline type (cubic | catmullrom | formula) 2c+b=1",
|
|
Packit |
bc1512 |
"cubic",
|
|
Packit |
bc1512 |
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_sampler_cubic_finalize (GObject *object)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_free (GEGL_SAMPLER_CUBIC (object)->type);
|
|
Packit |
bc1512 |
G_OBJECT_CLASS (gegl_sampler_cubic_parent_class)->finalize (object);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_sampler_cubic_init (GeglSamplerCubic *self)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GEGL_SAMPLER (self)->context_rect[0].x = -1;
|
|
Packit |
bc1512 |
GEGL_SAMPLER (self)->context_rect[0].y = -1;
|
|
Packit |
bc1512 |
GEGL_SAMPLER (self)->context_rect[0].width = 4;
|
|
Packit |
bc1512 |
GEGL_SAMPLER (self)->context_rect[0].height = 4;
|
|
Packit |
bc1512 |
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
|
|
Packit |
bc1512 |
self->b=1.0;
|
|
Packit |
bc1512 |
self->c=0.0;
|
|
Packit |
bc1512 |
self->type = g_strdup("cubic");
|
|
Packit |
bc1512 |
if (strcmp (self->type, "cubic"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* cubic B-spline */
|
|
Packit |
bc1512 |
self->b = 0.0;
|
|
Packit |
bc1512 |
self->c = 0.5;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (strcmp (self->type, "catmullrom"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* Catmull-Rom spline */
|
|
Packit |
bc1512 |
self->b = 1.0;
|
|
Packit |
bc1512 |
self->c = 0.0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else if (strcmp (self->type, "formula"))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
self->c = (1.0 - self->b) / 2.0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
void
|
|
Packit |
bc1512 |
gegl_sampler_cubic_get (GeglSampler *self,
|
|
Packit |
bc1512 |
gdouble x,
|
|
Packit |
bc1512 |
gdouble y,
|
|
Packit |
bc1512 |
GeglMatrix2 *scale,
|
|
Packit |
bc1512 |
void *output)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglSamplerCubic *cubic = (GeglSamplerCubic*)(self);
|
|
Packit |
bc1512 |
GeglRectangle context_rect;
|
|
Packit |
bc1512 |
const gint offsets[16]={-4-64*4, 4, 4, 4,
|
|
Packit |
bc1512 |
(64-3)*4, 4, 4, 4,
|
|
Packit |
bc1512 |
(64-3)*4, 4, 4, 4,
|
|
Packit |
bc1512 |
(64-3)*4, 4, 4, 4};
|
|
Packit |
bc1512 |
gfloat *sampler_bptr;
|
|
Packit |
bc1512 |
gfloat factor;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gfloat newval[4] = {0.0, 0.0, 0.0, 0.0};
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gint u,v;
|
|
Packit |
bc1512 |
gint dx,dy;
|
|
Packit |
bc1512 |
gint i;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
context_rect = self->context_rect[0];
|
|
Packit |
bc1512 |
dx = (gint) x;
|
|
Packit |
bc1512 |
dy = (gint) y;
|
|
Packit |
bc1512 |
sampler_bptr = gegl_sampler_get_ptr (self, dx, dy);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
for (v=dy+context_rect.y, i=0; v < dy+context_rect.y+context_rect.height ; v++)
|
|
Packit |
bc1512 |
for (u=dx+context_rect.x ; u < dx+context_rect.x+context_rect.width ; u++, i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/*sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);*/
|
|
Packit |
bc1512 |
sampler_bptr += offsets[i];
|
|
Packit |
bc1512 |
factor = cubicKernel (y - v, cubic->b, cubic->c) *
|
|
Packit |
bc1512 |
cubicKernel (x - u, cubic->b, cubic->c);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
newval[0] += factor * sampler_bptr[0];
|
|
Packit |
bc1512 |
newval[1] += factor * sampler_bptr[1];
|
|
Packit |
bc1512 |
newval[2] += factor * sampler_bptr[2];
|
|
Packit |
bc1512 |
newval[3] += factor * sampler_bptr[3];
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
babl_process (self->fish, newval, output, 1);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
get_property (GObject *object,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglSamplerCubic *self = GEGL_SAMPLER_CUBIC (object);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
switch (prop_id)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
case PROP_B:
|
|
Packit |
bc1512 |
g_value_set_double (value, self->b);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
case PROP_TYPE:
|
|
Packit |
bc1512 |
g_value_set_string (value, self->type);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
default:
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
set_property (GObject *object,
|
|
Packit |
bc1512 |
guint prop_id,
|
|
Packit |
bc1512 |
const GValue *value,
|
|
Packit |
bc1512 |
GParamSpec *pspec)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglSamplerCubic *self = GEGL_SAMPLER_CUBIC (object);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
switch (prop_id)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
case PROP_B:
|
|
Packit |
bc1512 |
self->b = g_value_get_double (value);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
case PROP_TYPE:
|
|
Packit |
bc1512 |
if (self->type)
|
|
Packit |
bc1512 |
g_free (self->type);
|
|
Packit |
bc1512 |
self->type = g_value_dup_string (value);
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
default:
|
|
Packit |
bc1512 |
break;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline gfloat
|
|
Packit |
bc1512 |
cubicKernel (gfloat x,
|
|
Packit |
bc1512 |
gfloat b,
|
|
Packit |
bc1512 |
gfloat c)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gfloat weight, x2, x3;
|
|
Packit |
bc1512 |
gfloat ax = x;
|
|
Packit |
bc1512 |
if (ax < 0.0)
|
|
Packit |
bc1512 |
ax *= -1.0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (ax > 2) return 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
x3 = ax * ax * ax;
|
|
Packit |
bc1512 |
x2 = ax * ax;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (ax < 1)
|
|
Packit |
bc1512 |
weight = (12 - 9 * b - 6 * c) * x3 +
|
|
Packit |
bc1512 |
(-18 + 12 * b + 6 * c) * x2 +
|
|
Packit |
bc1512 |
(6 - 2 * b);
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
weight = (-b - 6 * c) * x3 +
|
|
Packit |
bc1512 |
(6 * b + 30 * c) * x2 +
|
|
Packit |
bc1512 |
(-12 * b - 48 * c) * ax +
|
|
Packit |
bc1512 |
(8 * b + 24 * c);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return weight / 6.0;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|