Blame gegl/buffer/gegl-sampler-cubic.c

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