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