Blame gegl/buffer/gegl-sampler.c

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
 * 2007 © Øyvind Kolås
Packit Service 2781ba
 * 2009 © Nicolas Robidoux
Packit Service 2781ba
 * 2011 © Adam Turcotte
Packit Service 2781ba
 */
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
Packit Service 2781ba
#include <glib-object.h>
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
#include <math.h>
Packit Service 2781ba
Packit Service 2781ba
#include "gegl.h"
Packit Service 2781ba
#include "gegl-types-internal.h"
Packit Service 2781ba
#include "gegl-buffer.h"
Packit Service 2781ba
#include "gegl-utils.h"
Packit Service 2781ba
#include "gegl-buffer-private.h"
Packit Service 2781ba
Packit Service 2781ba
#include "gegl-sampler-nearest.h"
Packit Service 2781ba
#include "gegl-sampler-linear.h"
Packit Service 2781ba
#include "gegl-sampler-cubic.h"
Packit Service 2781ba
#include "gegl-sampler-lohalo.h"
Packit Service 2781ba
Packit Service 2781ba
enum
Packit Service 2781ba
{
Packit Service 2781ba
  PROP_0,
Packit Service 2781ba
  PROP_BUFFER,
Packit Service 2781ba
  PROP_FORMAT,
Packit Service 2781ba
  PROP_CONTEXT_RECT,
Packit Service 2781ba
  PROP_LAST
Packit Service 2781ba
};
Packit Service 2781ba
Packit Service 2781ba
static void gegl_sampler_class_init (GeglSamplerClass *klass);
Packit Service 2781ba
Packit Service 2781ba
static void gegl_sampler_init (GeglSampler *self);
Packit Service 2781ba
Packit Service 2781ba
static void finalize (GObject *gobject);
Packit Service 2781ba
Packit Service 2781ba
static void dispose (GObject *gobject);
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
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 set_buffer (GeglSampler  *self,
Packit Service 2781ba
                        GeglBuffer   *buffer);
Packit Service 2781ba
Packit Service 2781ba
G_DEFINE_TYPE (GeglSampler, gegl_sampler, G_TYPE_OBJECT)
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_sampler_class_init (GeglSamplerClass *klass)
Packit Service 2781ba
{
Packit Service 2781ba
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
Packit Service 2781ba
Packit Service 2781ba
  object_class->finalize = finalize;
Packit Service 2781ba
  object_class->dispose = dispose;
Packit Service 2781ba
Packit Service 2781ba
  klass->prepare = NULL;
Packit Service 2781ba
  klass->get     = NULL;
Packit Service 2781ba
  klass->set_buffer   = set_buffer;
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
  g_object_class_install_property (
Packit Service 2781ba
                 object_class,
Packit Service 2781ba
                 PROP_FORMAT,
Packit Service 2781ba
                 g_param_spec_pointer ("format",
Packit Service 2781ba
                                       "format",
Packit Service 2781ba
                                       "babl format",
Packit Service 2781ba
                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
Packit Service 2781ba
Packit Service 2781ba
  g_object_class_install_property (
Packit Service 2781ba
                   object_class,
Packit Service 2781ba
                   PROP_BUFFER,
Packit Service 2781ba
                   g_param_spec_object ("buffer",
Packit Service 2781ba
                                        "Buffer",
Packit Service 2781ba
                                        "Input pad, for image buffer input.",
Packit Service 2781ba
                                        GEGL_TYPE_BUFFER,
Packit Service 2781ba
                                        G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_sampler_init (GeglSampler *self)
Packit Service 2781ba
{
Packit Service 2781ba
  int i;
Packit Service 2781ba
  self->buffer = NULL;
Packit Service 2781ba
  for (i=0; i
Packit Service 2781ba
    GeglRectangle context_rect = {0,0,1,1};
Packit Service 2781ba
    GeglRectangle sampler_rectangle = {0,0,0,0};
Packit Service 2781ba
    self->sampler_buffer[i] = NULL;
Packit Service 2781ba
    self->context_rect[i] = context_rect;
Packit Service 2781ba
    self->sampler_rectangle[i] = sampler_rectangle;
Packit Service 2781ba
  }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_sampler_get (GeglSampler   *self,
Packit Service 2781ba
                  gdouble        x,
Packit Service 2781ba
                  gdouble        y,
Packit Service 2781ba
                  GeglMatrix2   *scale,
Packit Service 2781ba
                  void          *output,
Packit Service 2781ba
                  GeglAbyssPolicy repeat_mode)
Packit Service 2781ba
{
Packit Service 2781ba
  self->get (self, x, y, scale, output);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_sampler_prepare (GeglSampler *self)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSamplerClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_SAMPLER (self));
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_SAMPLER_GET_CLASS (self);
Packit Service 2781ba
Packit Service 2781ba
  if (klass->prepare)
Packit Service 2781ba
    klass->prepare (self);
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
  self->fish = babl_fish (self->interpolate_format, self->format);
Packit Service 2781ba
Packit Service 2781ba
  /*
Packit Service 2781ba
   * This makes the cache rect invalid, in case the data in the buffer
Packit Service 2781ba
   * has changed:
Packit Service 2781ba
   */
Packit Service 2781ba
  self->sampler_rectangle[0].width = 0;
Packit Service 2781ba
  self->sampler_rectangle[0].height = 0;
Packit Service 2781ba
Packit Service 2781ba
#if 0
Packit Service 2781ba
  if (self->cache_buffer) /* Force a regetting of the region, even
Packit Service 2781ba
                             though the cached getter may be valid. */
Packit Service 2781ba
    {
Packit Service 2781ba
      g_free (self->cache_buffer);
Packit Service 2781ba
      self->cache_buffer = NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
#endif
Packit Service 2781ba
  self->get = klass->get; /* cache the sampler in the instance */
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_sampler_set_buffer (GeglSampler *self, GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSamplerClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_SAMPLER (self));
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_SAMPLER_GET_CLASS (self);
Packit Service 2781ba
Packit Service 2781ba
  if (klass->set_buffer)
Packit Service 2781ba
    klass->set_buffer (self, buffer);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
finalize (GObject *gobject)
Packit Service 2781ba
{
Packit Service 2781ba
  int i;
Packit Service 2781ba
  GeglSampler *sampler = GEGL_SAMPLER (gobject);
Packit Service 2781ba
  for (i=0; i
Packit Service 2781ba
    {
Packit Service 2781ba
      if (sampler->sampler_buffer[i])
Packit Service 2781ba
        {
Packit Service 2781ba
          g_free (sampler->sampler_buffer[i]);
Packit Service 2781ba
          sampler->sampler_buffer[i] = NULL;
Packit Service 2781ba
        }
Packit Service 2781ba
    }
Packit Service 2781ba
  G_OBJECT_CLASS (gegl_sampler_parent_class)->finalize (gobject);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
dispose (GObject *gobject)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSampler *sampler = GEGL_SAMPLER (gobject);
Packit Service 2781ba
  if (sampler->buffer)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_object_unref (sampler->buffer);
Packit Service 2781ba
      sampler->buffer = NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
  G_OBJECT_CLASS (gegl_sampler_parent_class)->dispose (gobject);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/*
Packit Service 2781ba
 * Gets a pointer to the center pixel, within a buffer that has a
Packit Service 2781ba
 * rowstride of 64px * 16bpp:
Packit Service 2781ba
 */
Packit Service 2781ba
gfloat *
Packit Service 2781ba
gegl_sampler_get_ptr (GeglSampler *const sampler,
Packit Service 2781ba
                      const gint         x,
Packit Service 2781ba
                      const gint         y)
Packit Service 2781ba
{
Packit Service 2781ba
  guchar *buffer_ptr;
Packit Service 2781ba
  gint    dx;
Packit Service 2781ba
  gint    dy;
Packit Service 2781ba
  gint    sof;
Packit Service 2781ba
Packit Service 2781ba
  const gint bpp =
Packit Service 2781ba
    babl_format_get_bytes_per_pixel (sampler->interpolate_format);
Packit Service 2781ba
Packit Service 2781ba
  /*
Packit Service 2781ba
   * maximum_width_and_height is the largest number of pixels which
Packit Service 2781ba
   * can be be requested in the horizontal or vertical directions (64
Packit Service 2781ba
   * in GEGL).
Packit Service 2781ba
   */
Packit Service 2781ba
  const gint maximum_width_and_height = 64;
Packit Service 2781ba
  g_assert (sampler->context_rect[0].width  <= maximum_width_and_height);
Packit Service 2781ba
  g_assert (sampler->context_rect[0].height <= maximum_width_and_height);
Packit Service 2781ba
Packit Service 2781ba
  if (( sampler->sampler_buffer[0] == NULL )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x + sampler->context_rect[0].x < sampler->sampler_rectangle[0].x )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y + sampler->context_rect[0].y < sampler->sampler_rectangle[0].y )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x + sampler->context_rect[0].x + sampler->context_rect[0].width
Packit Service 2781ba
        > sampler->sampler_rectangle[0].x + sampler->sampler_rectangle[0].width )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y + sampler->context_rect[0].y + sampler->context_rect[0].height
Packit Service 2781ba
        > sampler->sampler_rectangle[0].y + sampler->sampler_rectangle[0].height ))
Packit Service 2781ba
    {
Packit Service 2781ba
      /*
Packit Service 2781ba
       * fetch_rectangle will become the value of
Packit Service 2781ba
       * sampler->sampler_rectangle[0]:
Packit Service 2781ba
       */
Packit Service 2781ba
      GeglRectangle fetch_rectangle;
Packit Service 2781ba
Packit Service 2781ba
      /*
Packit Service 2781ba
       * Override the fetch rectangle needed by the sampler, hoping
Packit Service 2781ba
       * that the extra pixels are useful for subsequent requests,
Packit Service 2781ba
       * assuming that it is more likely that further access is to the
Packit Service 2781ba
       * right or down of our currently requested
Packit Service 2781ba
       * position. Consequently, we move the top left corner of the
Packit Service 2781ba
       * context_rect by about one fourth of the maximal distance we
Packit Service 2781ba
       * can (one fourth of one half = one eight). Given that the
Packit Service 2781ba
       * maximum width and height of the fetch_rectangle is 64, so
Packit Service 2781ba
       * that half of it is 32, one fourth of the elbow room is at
Packit Service 2781ba
       * most 8. If context_rect is large, the corner is not moved
Packit Service 2781ba
       * much if at all, as should be.
Packit Service 2781ba
       */
Packit Service 2781ba
      fetch_rectangle.x =
Packit Service 2781ba
        x + sampler->context_rect[0].x
Packit Service 2781ba
        - ( maximum_width_and_height - sampler->context_rect[0].width  ) / 8;
Packit Service 2781ba
      fetch_rectangle.y =
Packit Service 2781ba
        y + sampler->context_rect[0].y
Packit Service 2781ba
        - ( maximum_width_and_height - sampler->context_rect[0].height ) / 8;
Packit Service 2781ba
Packit Service 2781ba
      fetch_rectangle.width  = maximum_width_and_height;
Packit Service 2781ba
      fetch_rectangle.height = maximum_width_and_height;
Packit Service 2781ba
Packit Service 2781ba
      if (sampler->sampler_buffer[0] == NULL)
Packit Service 2781ba
        {
Packit Service 2781ba
          /*
Packit Service 2781ba
           * Always request the same amount of pixels:
Packit Service 2781ba
           */
Packit Service 2781ba
          sampler->sampler_buffer[0] =
Packit Service 2781ba
            g_malloc0 (( maximum_width_and_height * maximum_width_and_height )
Packit Service 2781ba
                       * bpp);
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      gegl_buffer_get (sampler->buffer,
Packit Service 2781ba
                       &fetch_rectangle,
Packit Service 2781ba
                       1.0,
Packit Service 2781ba
                       sampler->interpolate_format,
Packit Service 2781ba
                       sampler->sampler_buffer[0],
Packit Service 2781ba
                       GEGL_AUTO_ROWSTRIDE,
Packit Service 2781ba
                       GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
      sampler->sampler_rectangle[0] = fetch_rectangle;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  dx = x - sampler->sampler_rectangle[0].x;
Packit Service 2781ba
  dy = y - sampler->sampler_rectangle[0].y;
Packit Service 2781ba
  buffer_ptr = (guchar *)sampler->sampler_buffer[0];
Packit Service 2781ba
  sof = ( dx + dy * sampler->sampler_rectangle[0].width ) * bpp;
Packit Service 2781ba
Packit Service 2781ba
  return (gfloat*)(buffer_ptr+sof);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gfloat *
Packit Service 2781ba
gegl_sampler_get_from_buffer (GeglSampler *const sampler,
Packit Service 2781ba
                              const gint         x,
Packit Service 2781ba
                              const gint         y)
Packit Service 2781ba
{
Packit Service 2781ba
  guchar *buffer_ptr;
Packit Service 2781ba
  gint    dx;
Packit Service 2781ba
  gint    dy;
Packit Service 2781ba
  gint    sof;
Packit Service 2781ba
Packit Service 2781ba
  const gint bpp =
Packit Service 2781ba
    babl_format_get_bytes_per_pixel (sampler->interpolate_format);
Packit Service 2781ba
Packit Service 2781ba
  /*
Packit Service 2781ba
   * maximum_width_and_height is the largest number of pixels which
Packit Service 2781ba
   * can be be requested in the horizontal or vertical directions (64
Packit Service 2781ba
   * in GEGL).
Packit Service 2781ba
   */
Packit Service 2781ba
  const gint maximum_width_and_height = 64;
Packit Service 2781ba
  g_assert (sampler->context_rect[0].width  <= maximum_width_and_height);
Packit Service 2781ba
  g_assert (sampler->context_rect[0].height <= maximum_width_and_height);
Packit Service 2781ba
Packit Service 2781ba
  if (( sampler->sampler_buffer[0] == NULL )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x < sampler->sampler_rectangle[0].x )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y < sampler->sampler_rectangle[0].y )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x >= sampler->sampler_rectangle[0].x + sampler->sampler_rectangle[0].width )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y >= sampler->sampler_rectangle[0].y + sampler->sampler_rectangle[0].height ))
Packit Service 2781ba
    {
Packit Service 2781ba
      /*
Packit Service 2781ba
       * fetch_rectangle will become the value of
Packit Service 2781ba
       * sampler->sampler_rectangle:
Packit Service 2781ba
       */
Packit Service 2781ba
      GeglRectangle fetch_rectangle;
Packit Service 2781ba
Packit Service 2781ba
      fetch_rectangle.x =
Packit Service 2781ba
        x - ( maximum_width_and_height - sampler->context_rect[0].width  ) / 8;
Packit Service 2781ba
      fetch_rectangle.y =
Packit Service 2781ba
        y - ( maximum_width_and_height - sampler->context_rect[0].height ) / 8;
Packit Service 2781ba
Packit Service 2781ba
      fetch_rectangle.width  = maximum_width_and_height;
Packit Service 2781ba
      fetch_rectangle.height = maximum_width_and_height;
Packit Service 2781ba
Packit Service 2781ba
      if (sampler->sampler_buffer[0] == NULL)
Packit Service 2781ba
        {
Packit Service 2781ba
          /*
Packit Service 2781ba
           * Always request the same amount of pixels:
Packit Service 2781ba
           */
Packit Service 2781ba
          sampler->sampler_buffer[0] =
Packit Service 2781ba
            g_malloc0 (( maximum_width_and_height * maximum_width_and_height )
Packit Service 2781ba
                       * bpp);
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      gegl_buffer_get (sampler->buffer,
Packit Service 2781ba
                       &fetch_rectangle,
Packit Service 2781ba
                       1.0,
Packit Service 2781ba
                       sampler->interpolate_format,
Packit Service 2781ba
                       sampler->sampler_buffer[0],
Packit Service 2781ba
                       GEGL_AUTO_ROWSTRIDE,
Packit Service 2781ba
                       GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
      sampler->sampler_rectangle[0] = fetch_rectangle;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  dx = x - sampler->sampler_rectangle[0].x;
Packit Service 2781ba
  dy = y - sampler->sampler_rectangle[0].y;
Packit Service 2781ba
  buffer_ptr = (guchar *)sampler->sampler_buffer[0];
Packit Service 2781ba
  sof = ( dx + dy * sampler->sampler_rectangle[0].width ) * bpp;
Packit Service 2781ba
Packit Service 2781ba
  return (gfloat*)(buffer_ptr+sof);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gfloat *
Packit Service 2781ba
gegl_sampler_get_from_mipmap (GeglSampler *const sampler,
Packit Service 2781ba
                              const gint         x,
Packit Service 2781ba
                              const gint         y,
Packit Service 2781ba
                              const gint         level)
Packit Service 2781ba
{
Packit Service 2781ba
  guchar *buffer_ptr;
Packit Service 2781ba
  gint    dx;
Packit Service 2781ba
  gint    dy;
Packit Service 2781ba
  gint    sof;
Packit Service 2781ba
Packit Service 2781ba
  const gdouble scale = 1. / ( (gdouble) (1<
Packit Service 2781ba
Packit Service 2781ba
  const gint bpp =
Packit Service 2781ba
    babl_format_get_bytes_per_pixel (sampler->interpolate_format);
Packit Service 2781ba
Packit Service 2781ba
  /*
Packit Service 2781ba
   * maximum_width_and_height is the largest number of pixels which
Packit Service 2781ba
   * can be be requested in the horizontal or vertical directions (64
Packit Service 2781ba
   * in GEGL).
Packit Service 2781ba
   */
Packit Service 2781ba
  const gint maximum_width_and_height = 64;
Packit Service 2781ba
  g_assert (sampler->context_rect[level].width  <= maximum_width_and_height);
Packit Service 2781ba
  g_assert (sampler->context_rect[level].height <= maximum_width_and_height);
Packit Service 2781ba
  g_assert (level >= 0 && level < GEGL_SAMPLER_MIPMAP_LEVELS);
Packit Service 2781ba
Packit Service 2781ba
  if (( sampler->sampler_buffer[level] == NULL )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x + sampler->context_rect[level].x < sampler->sampler_rectangle[level].x )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y + sampler->context_rect[level].y < sampler->sampler_rectangle[level].y )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( x + sampler->context_rect[level].x + sampler->context_rect[level].width
Packit Service 2781ba
        > sampler->sampler_rectangle[level].x + sampler->sampler_rectangle[level].width )
Packit Service 2781ba
      ||
Packit Service 2781ba
      ( y + sampler->context_rect[level].y + sampler->context_rect[level].height
Packit Service 2781ba
        > sampler->sampler_rectangle[level].y + sampler->sampler_rectangle[level].height ))
Packit Service 2781ba
    {
Packit Service 2781ba
      /*
Packit Service 2781ba
       * fetch_rectangle will become the value of
Packit Service 2781ba
       * sampler->sampler_rectangle[level]:
Packit Service 2781ba
       */
Packit Service 2781ba
      GeglRectangle fetch_rectangle;
Packit Service 2781ba
Packit Service 2781ba
      /*
Packit Service 2781ba
       * Override the fetch rectangle needed by the sampler, hoping
Packit Service 2781ba
       * that the extra pixels are useful for subsequent requests,
Packit Service 2781ba
       * assuming that it is more likely that further access is to the
Packit Service 2781ba
       * right or down of our currently requested
Packit Service 2781ba
       * position. Consequently, we move the top left corner of the
Packit Service 2781ba
       * context_rect by about one fourth of the maximal distance we
Packit Service 2781ba
       * can (one fourth of one half = one eight). Given that the
Packit Service 2781ba
       * maximum width and height of the fetch_rectangle is 64, so
Packit Service 2781ba
       * that half of it is 32, one fourth of the elbow room is at
Packit Service 2781ba
       * most 8. If context_rect is large, the corner is not moved
Packit Service 2781ba
       * much if at all, as should be.
Packit Service 2781ba
       */
Packit Service 2781ba
      fetch_rectangle.x =
Packit Service 2781ba
        x + sampler->context_rect[level].x
Packit Service 2781ba
        - ( maximum_width_and_height - sampler->context_rect[level].width  ) / 8;
Packit Service 2781ba
      fetch_rectangle.y =
Packit Service 2781ba
        y + sampler->context_rect[level].y
Packit Service 2781ba
        - ( maximum_width_and_height - sampler->context_rect[level].height ) / 8;
Packit Service 2781ba
Packit Service 2781ba
      fetch_rectangle.width  = maximum_width_and_height;
Packit Service 2781ba
      fetch_rectangle.height = maximum_width_and_height;
Packit Service 2781ba
Packit Service 2781ba
      if (sampler->sampler_buffer[level] == NULL)
Packit Service 2781ba
        {
Packit Service 2781ba
          /*
Packit Service 2781ba
           * Always request the same amount of pixels:
Packit Service 2781ba
           */
Packit Service 2781ba
          sampler->sampler_buffer[level] =
Packit Service 2781ba
            g_malloc0 (( maximum_width_and_height * maximum_width_and_height )
Packit Service 2781ba
                       * bpp);
Packit Service 2781ba
        }
Packit Service 2781ba
Packit Service 2781ba
      gegl_buffer_get (sampler->buffer,
Packit Service 2781ba
                       &fetch_rectangle,
Packit Service 2781ba
                       scale,
Packit Service 2781ba
                       sampler->interpolate_format,
Packit Service 2781ba
                       sampler->sampler_buffer[level],
Packit Service 2781ba
                       GEGL_AUTO_ROWSTRIDE,
Packit Service 2781ba
                       GEGL_ABYSS_NONE);
Packit Service 2781ba
Packit Service 2781ba
      sampler->sampler_rectangle[level] = fetch_rectangle;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  dx = x - sampler->sampler_rectangle[level].x;
Packit Service 2781ba
  dy = y - sampler->sampler_rectangle[level].y;
Packit Service 2781ba
  buffer_ptr = (guchar *)sampler->sampler_buffer[level];
Packit Service 2781ba
  sof = ( dx + dy * sampler->sampler_rectangle[level].width ) * bpp;
Packit Service 2781ba
Packit Service 2781ba
  return (gfloat*)(buffer_ptr+sof);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
get_property (GObject    *object,
Packit Service 2781ba
              guint       property_id,
Packit Service 2781ba
              GValue     *value,
Packit Service 2781ba
              GParamSpec *pspec)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSampler *self = GEGL_SAMPLER (object);
Packit Service 2781ba
Packit Service 2781ba
  switch (property_id)
Packit Service 2781ba
    {
Packit Service 2781ba
      case PROP_BUFFER:
Packit Service 2781ba
        g_value_set_object (value, self->buffer);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_FORMAT:
Packit Service 2781ba
        g_value_set_pointer (value, (void*)self->format);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      default:
Packit Service 2781ba
        break;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
set_property (GObject      *object,
Packit Service 2781ba
              guint         property_id,
Packit Service 2781ba
              const GValue *value,
Packit Service 2781ba
              GParamSpec   *pspec)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSampler *self = GEGL_SAMPLER (object);
Packit Service 2781ba
Packit Service 2781ba
  switch (property_id)
Packit Service 2781ba
    {
Packit Service 2781ba
      case PROP_BUFFER:
Packit Service 2781ba
        self->buffer = GEGL_BUFFER (g_value_dup_object (value));
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      case PROP_FORMAT:
Packit Service 2781ba
        self->format = g_value_get_pointer (value);
Packit Service 2781ba
        break;
Packit Service 2781ba
Packit Service 2781ba
      default:
Packit Service 2781ba
        break;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
set_buffer (GeglSampler *self, GeglBuffer *buffer)
Packit Service 2781ba
{
Packit Service 2781ba
   if (self->buffer != buffer)
Packit Service 2781ba
     {
Packit Service 2781ba
       if (GEGL_IS_BUFFER(self->buffer))
Packit Service 2781ba
         g_object_unref(self->buffer);
Packit Service 2781ba
       if (GEGL_IS_BUFFER (buffer))
Packit Service 2781ba
         self->buffer = gegl_buffer_dup (buffer);
Packit Service 2781ba
       else
Packit Service 2781ba
         self->buffer = NULL;
Packit Service 2781ba
     }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglSamplerType
Packit Service 2781ba
gegl_sampler_type_from_string (const gchar *string)
Packit Service 2781ba
{
Packit Service 2781ba
  if (g_str_equal (string, "nearest") ||
Packit Service 2781ba
      g_str_equal (string, "none"))
Packit Service 2781ba
    return GEGL_SAMPLER_NEAREST;
Packit Service 2781ba
Packit Service 2781ba
  if (g_str_equal (string, "linear") ||
Packit Service 2781ba
      g_str_equal (string, "bilinear"))
Packit Service 2781ba
    return GEGL_SAMPLER_LINEAR;
Packit Service 2781ba
Packit Service 2781ba
  if (g_str_equal (string, "cubic") ||
Packit Service 2781ba
      g_str_equal (string, "bicubic"))
Packit Service 2781ba
    return GEGL_SAMPLER_CUBIC;
Packit Service 2781ba
Packit Service 2781ba
  if (g_str_equal (string, "lohalo"))
Packit Service 2781ba
    return GEGL_SAMPLER_LOHALO;
Packit Service 2781ba
Packit Service 2781ba
  return GEGL_SAMPLER_NEAREST;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GType
Packit Service 2781ba
gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type);
Packit Service 2781ba
GType
Packit Service 2781ba
gegl_sampler_gtype_from_enum (GeglSamplerType sampler_type)
Packit Service 2781ba
{
Packit Service 2781ba
  switch (sampler_type)
Packit Service 2781ba
    {
Packit Service 2781ba
      case GEGL_SAMPLER_NEAREST:
Packit Service 2781ba
        return GEGL_TYPE_SAMPLER_NEAREST;
Packit Service 2781ba
      case GEGL_SAMPLER_LINEAR:
Packit Service 2781ba
        return GEGL_TYPE_SAMPLER_LINEAR;
Packit Service 2781ba
      case GEGL_SAMPLER_CUBIC:
Packit Service 2781ba
        return GEGL_TYPE_SAMPLER_CUBIC;
Packit Service 2781ba
      case GEGL_SAMPLER_LOHALO:
Packit Service 2781ba
        return GEGL_TYPE_SAMPLER_LOHALO;
Packit Service 2781ba
      default:
Packit Service 2781ba
        return GEGL_TYPE_SAMPLER_LINEAR;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglSampler *
Packit Service 2781ba
gegl_buffer_sampler_new (GeglBuffer       *buffer,
Packit Service 2781ba
                         const Babl       *format,
Packit Service 2781ba
                         GeglSamplerType   sampler_type)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglSampler          *sampler;
Packit Service 2781ba
  GType                 desired_type;
Packit Service 2781ba
  if (format == NULL)
Packit Service 2781ba
    format = babl_format ("RaGaBaA float");
Packit Service 2781ba
  desired_type = gegl_sampler_gtype_from_enum (sampler_type);
Packit Service 2781ba
  sampler = g_object_new (desired_type,
Packit Service 2781ba
                          "buffer", buffer,
Packit Service 2781ba
                          "format", format,
Packit Service 2781ba
                          NULL);
Packit Service 2781ba
  gegl_sampler_prepare (sampler);
Packit Service 2781ba
  return sampler;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const GeglRectangle*
Packit Service 2781ba
gegl_sampler_get_context_rect (GeglSampler *sampler)
Packit Service 2781ba
{
Packit Service 2781ba
  return &(sampler->context_rect[0]);
Packit Service 2781ba
}