gegl r2442 - in trunk: . gegl/buffer operations/affine
- From: ok svn gnome org
- To: svn-commits-list gnome org
- Subject: gegl r2442 - in trunk: . gegl/buffer operations/affine
- Date: Sat, 14 Jun 2008 13:25:17 +0000 (UTC)
Author: ok
Date: Sat Jun 14 13:25:17 2008
New Revision: 2442
URL: http://svn.gnome.org/viewvc/gegl?rev=2442&view=rev
Log:
Applied patch from Bug #360888 - Adapt cubic and lanczos samplers for
new framework.
The patch isn't closed yet, but the code for nearest and linear is
stable now and the rest of the code delta is quite large. The patch
has been adapted to not introduce new API and the cubic and lanczos
filters are disabled due to artifacts.
* gegl/buffer/gegl-buffer-access.c:
* gegl/buffer/gegl-buffer-types.h:
* gegl/buffer/gegl-buffer.c:
* gegl/buffer/gegl-buffer.h:
* gegl/buffer/gegl-sampler-cubic.c:
* gegl/buffer/gegl-sampler-lanczos.c:
* gegl/buffer/gegl-sampler-linear.c:
* gegl/buffer/gegl-sampler-nearest.c:
* gegl/buffer/gegl-sampler.c:
* gegl/buffer/gegl-sampler.h:
* operations/affine/affine.c:
* operations/affine/affine.h:
Modified:
trunk/ChangeLog
trunk/gegl/buffer/gegl-buffer-access.c
trunk/gegl/buffer/gegl-buffer-types.h
trunk/gegl/buffer/gegl-buffer.c
trunk/gegl/buffer/gegl-buffer.h
trunk/gegl/buffer/gegl-sampler-cubic.c
trunk/gegl/buffer/gegl-sampler-lanczos.c
trunk/gegl/buffer/gegl-sampler-linear.c
trunk/gegl/buffer/gegl-sampler-nearest.c
trunk/gegl/buffer/gegl-sampler.c
trunk/gegl/buffer/gegl-sampler.h
trunk/operations/affine/affine.c
trunk/operations/affine/affine.h
Modified: trunk/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-access.c (original)
+++ trunk/gegl/buffer/gegl-buffer-access.c Sat Jun 14 13:25:17 2008
@@ -35,6 +35,7 @@
#include "gegl-sampler-nearest.h"
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
+#include "gegl-sampler-lanczos.h"
#include "gegl-buffer-index.h"
#include "gegl-tile-backend.h"
#include "gegl-buffer-iterator.h"
@@ -300,7 +301,7 @@
buffer->hot_tile = NULL;
}
if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))
- {
+ {
((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))->x =buffer->extent.x;
((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))->y =buffer->extent.y;
((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))->width =buffer->extent.width;
@@ -1087,6 +1088,7 @@
const Babl *format,
GeglInterpolation interpolation)
{
+ GType desired_type;
g_return_if_fail (GEGL_IS_BUFFER (buffer));
/*#define USE_WORKING_SHORTCUT*/
@@ -1099,26 +1101,19 @@
g_static_rec_mutex_lock (&mutex);
#endif
+ desired_type = gegl_sampler_type_from_interpolation (interpolation);
+
+ if (buffer->sampler != NULL &&
+ !G_TYPE_CHECK_INSTANCE_TYPE (buffer->sampler, desired_type))
+ {
+ g_object_unref(buffer->sampler);
+ buffer->sampler = NULL;
+ }
+
/* look up appropriate sampler,. */
if (buffer->sampler == NULL)
{
- /* FIXME: should probably check if the desired form of interpolation
- * changes from the currently cached sampler.
- */
- GType interpolation_type = 0;
-
- switch (interpolation)
- {
- case GEGL_INTERPOLATION_NEAREST:
- interpolation_type=GEGL_TYPE_SAMPLER_NEAREST;
- break;
- case GEGL_INTERPOLATION_LINEAR:
- interpolation_type=GEGL_TYPE_SAMPLER_LINEAR;
- break;
- default:
- g_warning ("unimplemented interpolation type %i", interpolation);
- }
- buffer->sampler = g_object_new (interpolation_type,
+ buffer->sampler = g_object_new (desired_type,
"buffer", buffer,
"format", format,
NULL);
@@ -1220,12 +1215,36 @@
GeglBuffer *
gegl_buffer_dup (GeglBuffer *buffer)
{
- GeglBuffer *new;
+ GeglBuffer *new_buffer;
g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
- new = gegl_buffer_new (gegl_buffer_get_extent (buffer), buffer->format);
+ new_buffer = gegl_buffer_new (gegl_buffer_get_extent (buffer), buffer->format);
gegl_buffer_copy (buffer, gegl_buffer_get_extent (buffer),
- new, gegl_buffer_get_extent (buffer));
- return new;
+ new_buffer, gegl_buffer_get_extent (buffer));
+ return new_buffer;
+}
+
+void
+gegl_buffer_sampler (GeglBuffer *buffer,
+ gdouble x,
+ gdouble y,
+ gdouble scale,
+ gpointer dest,
+ const Babl *format,
+ gpointer sampler2)
+{
+ GeglSampler *sampler = sampler2;
+ g_return_if_fail (GEGL_IS_BUFFER (buffer));
+ g_return_if_fail (GEGL_IS_SAMPLER (sampler));
+
+#if ENABLE_MP
+ g_static_rec_mutex_lock (&mutex);
+#endif
+
+ gegl_sampler_get (sampler, x, y, dest);
+
+#if ENABLE_MP
+ g_static_rec_mutex_unlock (&mutex);
+#endif
}
Modified: trunk/gegl/buffer/gegl-buffer-types.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer-types.h (original)
+++ trunk/gegl/buffer/gegl-buffer-types.h Sat Jun 14 13:25:17 2008
@@ -19,7 +19,7 @@
#ifndef __GEGL_BUFFER_TYPES_H__
#define __GEGL_BUFFER_TYPES_H__
-typedef struct _GeglSampler GeglSampler;
+
typedef struct _GeglTile GeglTile;
typedef struct _GeglTileClass GeglTileClass;
Modified: trunk/gegl/buffer/gegl-buffer.c
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.c (original)
+++ trunk/gegl/buffer/gegl-buffer.c Sat Jun 14 13:25:17 2008
@@ -61,6 +61,7 @@
#include "gegl-sampler-nearest.h"
#include "gegl-sampler-linear.h"
#include "gegl-sampler-cubic.h"
+#include "gegl-sampler-lanczos.h"
#include "gegl-types.h"
#include "gegl-utils.h"
#include "gegl-id-pool.h"
@@ -294,7 +295,7 @@
(*(GeglRectangle*)gegl_buffer_get_extent (buffer))=*extent;
if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))
- {
+ {
GeglBufferHeader *header = ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header));
header->x = buffer->extent.x;
header->y = buffer->extent.x;
@@ -464,7 +465,7 @@
}
source = g_object_new (GEGL_TYPE_BUFFER, "source", storage, NULL);
-
+
/* after construction,. x and y should be set to reflect
* the top level behavior exhibited by this buffer object.
*/
@@ -607,7 +608,7 @@
buffer->abyss.height = self.height;
}
- /* compute our own total shift <- this should probably happen
+ /* compute our own total shift <- this should probably happen
* approximatly first */
if (GEGL_IS_BUFFER (source))
{
@@ -637,7 +638,7 @@
GeglTile *tile = NULL;
source = handler->source;
- if (source)
+ if (source)
tile = gegl_tile_source_get_tile (source, x, y, z);
else
g_assert (0);
@@ -890,19 +891,6 @@
g_object_unref (buffer);
}
-GeglInterpolation
-gegl_buffer_interpolation_from_string (const gchar *string)
-{
- if (g_str_equal (string, "nearest") ||
- g_str_equal (string, "none"))
- return GEGL_INTERPOLATION_NEAREST;
-
- if (g_str_equal (string, "linear") ||
- g_str_equal (string, "bilinear"))
- return GEGL_INTERPOLATION_LINEAR;
-
- return GEGL_INTERPOLATION_NEAREST;
-}
Modified: trunk/gegl/buffer/gegl-buffer.h
==============================================================================
--- trunk/gegl/buffer/gegl-buffer.h (original)
+++ trunk/gegl/buffer/gegl-buffer.h Sat Jun 14 13:25:17 2008
@@ -41,7 +41,7 @@
*/
GType gegl_buffer_get_type (void) G_GNUC_CONST;
-/**
+/**
* gegl_buffer_new:
* @extent: the geometry of the buffer (origin, width and height) a
* GeglRectangle.
@@ -105,7 +105,7 @@
void gegl_buffer_flush (GeglBuffer *buffer);
-/**
+/**
* gegl_buffer_create_sub_buffer:
* @buffer: parent buffer.
* @extent: coordinates of new buffer.
@@ -273,7 +273,7 @@
const GeglRectangle *dst_rect);
-/**
+/**
* gegl_buffer_dup:
* @buffer: the GeglBuffer to duplicate.
*
@@ -286,6 +286,8 @@
typedef enum {
GEGL_INTERPOLATION_NEAREST = 0,
GEGL_INTERPOLATION_LINEAR,
+ GEGL_INTERPOLATION_CUBIC,
+ GEGL_INTERPOLATION_LANCZOS,
} GeglInterpolation;
/**
@@ -298,7 +300,9 @@
* @format: the format to store the sampled color in.
* @interpolation: the interpolation behavior to use, currently only nearest
* neighbour is implemented for this API, bilinear, bicubic and lanczos needs
- * to be ported from working code. Valid values: GEGL_INTERPOLATION_NEAREST
+ * to be ported from working code. Valid values: GEGL_INTERPOLATION_NEAREST and
+ * GEGL_INTERPOLATION_LINEAR, CUBIC and LANCZOS will become available for now they
+ * fall back to linear.
*
* Resample the buffer at some given coordinates using a specified format. For
* some operations this might be sufficient, but it might be considered
@@ -313,6 +317,7 @@
const Babl *format,
GeglInterpolation interpolation);
+
/**
* gegl_buffer_sample_cleanup:
* @buffer: the GeglBuffer to sample from
@@ -321,7 +326,7 @@
* automatically later when the buffer is destroyed, for long lived buffers
* cleaning up the sampling infrastructure when it has been used for its
* purpose will sometimes be more efficient).
- */
+ */
void gegl_buffer_sample_cleanup (GeglBuffer *buffer);
/**
@@ -333,6 +338,7 @@
*/
GeglInterpolation gegl_buffer_interpolation_from_string (const gchar *string);
+
/**
*/
#endif
Modified: trunk/gegl/buffer/gegl-sampler-cubic.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-cubic.c (original)
+++ trunk/gegl/buffer/gegl-sampler-cubic.c Sat Jun 14 13:25:17 2008
@@ -13,39 +13,40 @@
* You should have received a copy of the GNU Lesser General Public
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
*/
+
+#include <glib-object.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+#include "gegl-types.h"
+#include "gegl-buffer-private.h"
#include "gegl-sampler-cubic.h"
-#include "gegl-buffer-private.h" /* XXX */
#include <string.h>
#include <math.h>
-/* XXX WARNING: This code compiles, but is functionally broken, and
- * currently not used by the rest of GeglBuffer */
-
enum
{
PROP_0,
PROP_B,
+ PROP_C,
PROP_TYPE,
PROP_LAST
};
-static void get_property (GObject *gobject,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void set_property (GObject *gobject,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static inline float cubicKernel(float x, float b, float c);
-static void finalize (GObject *gobject);
-
-static void gegl_sampler_cubic_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
-
-static void gegl_sampler_cubic_prepare (GeglSampler *self);
+static void gegl_sampler_cubic_get (GeglSampler *sampler,
+ gdouble x,
+ gdouble y,
+ void *output);
+static void get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static inline gfloat cubicKernel (gfloat x,
+ gfloat b,
+ gfloat c);
G_DEFINE_TYPE (GeglSamplerCubic, gegl_sampler_cubic, GEGL_TYPE_SAMPLER)
@@ -53,14 +54,12 @@
static void
gegl_sampler_cubic_class_init (GeglSamplerCubicClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = finalize;
object_class->set_property = set_property;
object_class->get_property = get_property;
- sampler_class->prepare = gegl_sampler_cubic_prepare;
sampler_class->get = gegl_sampler_cubic_get;
g_object_class_install_property (object_class, PROP_B,
@@ -69,6 +68,15 @@
"B-spline parameter",
0.0,
1.0,
+ 1.0,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_C,
+ g_param_spec_double ("c",
+ "C",
+ "C-spline parameter",
+ 0.0,
+ 1.0,
0.0,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
@@ -78,21 +86,18 @@
"B-spline type (cubic | catmullrom | formula) 2c+b=1",
"cubic",
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
+
}
static void
gegl_sampler_cubic_init (GeglSamplerCubic *self)
{
-}
-
-void
-gegl_sampler_cubic_prepare (GeglSampler *sampler)
-{
- GeglSamplerCubic *self = GEGL_SAMPLER_CUBIC (sampler);
-
- /* fill the internal bufer */
-
- if (strcmp (self->type, "cubic"))
+ GEGL_SAMPLER (self)->context_rect= (GeglRectangle){-1,-1,4,4};
+ self->b=1;
+ self->c=0;
+ self->type = g_strdup("cubic");
+ return;
+ if (strcmp (self->type, "cubic"))
{
/* cubic B-spline */
self->b = 0.0;
@@ -106,95 +111,67 @@
}
else if (strcmp (self->type, "formula"))
{
- self->c = (1 - self->b) / 2.0;
+ self->c = (1.0 - self->b) / 2.0;
}
-}
-
-static void
-finalize (GObject *object)
-{
- GeglSamplerCubic *self = GEGL_SAMPLER_CUBIC (object);
-
- if (self->type)
- g_free (self->type);
- G_OBJECT_CLASS (gegl_sampler_cubic_parent_class)->finalize (object);
+ GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
void
-gegl_sampler_cubic_get (GeglSampler *sampler,
- gdouble x,
- gdouble y,
- void *output)
-{
- GeglSamplerCubic *self = GEGL_SAMPLER_CUBIC (sampler);
- gfloat *cache_buffer = sampler->cache_buffer;
- GeglRectangle *rectangle = &sampler->cache_rectangle;
- GeglBuffer *buffer = sampler->buffer;
- gfloat *buf_ptr;
- gfloat factor;
-
- gdouble arecip;
- gdouble newval[4];
-
- gfloat dst[4];
- gfloat abyss = 0.;
- gint i, j, pu, pv;
-
- gegl_sampler_fill_buffer (sampler, x, y);
- cache_buffer = sampler->cache_buffer;
- if (!buffer)
- return;
-
- if (x >= 0 &&
- y >= 0 &&
- x < buffer->extent.width &&
- y < buffer->extent.height)
+gegl_sampler_cubic_get (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output)
+{
+ GeglSamplerCubic *cubic = (GeglSamplerCubic*)(self);
+ GeglRectangle context_rect;
+ gfloat *sampler_bptr;
+ gfloat factor;
+ gdouble arecip;
+ gdouble newval[4];
+ gfloat abyss = 0.;
+ gfloat dst[4];
+ gint u,v;
+ gint dx,dy;
+
+ context_rect = self->context_rect;
+ dx = (gint) x;
+ dy = (gint) y;
+ newval[0] = newval[1] = newval[2] = newval[3] = 0.;
+ for (v=dy+context_rect.y ; v < dy+context_rect.y+context_rect.height ; v++)
+ for (u=dx+context_rect.x ; u < dx+context_rect.x+context_rect.width ; u++)
+ {
+ sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);
+ factor = cubicKernel (y - v, cubic->b, cubic->c) *
+ cubicKernel (x - u, cubic->b, cubic->c);
+ newval[0] += factor * sampler_bptr[0] * sampler_bptr[3];
+ newval[1] += factor * sampler_bptr[1] * sampler_bptr[3];
+ newval[2] += factor * sampler_bptr[2] * sampler_bptr[3];
+ newval[3] += factor * sampler_bptr[3];
+ }
+ if (newval[3] <= abyss)
{
- gint u = (gint) (x - rectangle->x);
- gint v = (gint) (y - rectangle->y);
- newval[0] = newval[1] = newval[2] = newval[3] = 0.0;
- for (j = -1; j <= 2; j++)
- for (i = -1; i <= 2; i++)
- {
- pu = CLAMP (u + i, 0, rectangle->width - 1);
- pv = CLAMP (v + j, 0, rectangle->height - 1);
- factor = cubicKernel ((y - rectangle->y) - pv, self->b, self->c) *
- cubicKernel ((x - rectangle->x) - pu, self->b, self->c);
- buf_ptr = cache_buffer + ((pv * rectangle->width + pu) * 4);
- newval[0] += factor * buf_ptr[0] * buf_ptr[3];
- newval[1] += factor * buf_ptr[1] * buf_ptr[3];
- newval[2] += factor * buf_ptr[2] * buf_ptr[3];
- newval[3] += factor * buf_ptr[3];
- }
- if (newval[3] <= 0.0)
- {
- arecip = 0.0;
- newval[3] = 0;
- }
- else if (newval[3] > G_MAXDOUBLE)
- {
- arecip = 1.0 / newval[3];
- newval[3] = G_MAXDOUBLE;
- }
- else
- {
- arecip = 1.0 / newval[3];
- }
-
- dst[0] = CLAMP (newval[0] * arecip, 0, G_MAXDOUBLE);
- dst[1] = CLAMP (newval[1] * arecip, 0, G_MAXDOUBLE);
- dst[2] = CLAMP (newval[2] * arecip, 0, G_MAXDOUBLE);
- dst[3] = CLAMP (newval[3], 0, G_MAXDOUBLE);
+ arecip = abyss;
+ newval[3] = abyss;
+ }
+ else if (newval[3] > G_MAXDOUBLE)
+ {
+ arecip = 1.0 / newval[3];
+ newval[3] = G_MAXDOUBLE;
}
else
{
- dst[0] = abyss;
- dst[1] = abyss;
- dst[2] = abyss;
- dst[3] = abyss;
+ arecip = 1.0 / newval[3];
}
- babl_process (babl_fish (sampler->interpolate_format, sampler->format),
+
+ /* FIXME: shouldn't clamp a computed value like this, it gets evaluated twice */
+ dst[0] = CLAMP (newval[0] * arecip, 0, G_MAXDOUBLE);
+ dst[1] = CLAMP (newval[1] * arecip, 0, G_MAXDOUBLE);
+ dst[2] = CLAMP (newval[2] * arecip, 0, G_MAXDOUBLE);
+ dst[3] = CLAMP (newval[3], 0, G_MAXDOUBLE);
+
+ babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
+
}
static void
@@ -236,10 +213,9 @@
case PROP_TYPE:
{
- const gchar *type = g_value_get_string (value);
if (self->type)
g_free (self->type);
- self->type = g_strdup (type);
+ self->type = g_strdup (g_value_get_string (value));
break;
}
@@ -248,10 +224,13 @@
}
}
-static inline float cubicKernel (float x, float b, float c)
-{
- float weight, x2, x3;
- float ax = (float) fabs (x);
+static inline gfloat
+cubicKernel (gfloat x,
+ gfloat b,
+ gfloat c)
+ {
+ gfloat weight, x2, x3;
+ gfloat ax = (gfloat) fabs (x);
if (ax > 2) return 0;
@@ -270,3 +249,4 @@
return weight * (1.0 / 6.0);
}
+
Modified: trunk/gegl/buffer/gegl-sampler-lanczos.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-lanczos.c (original)
+++ trunk/gegl/buffer/gegl-sampler-lanczos.c Sat Jun 14 13:25:17 2008
@@ -18,11 +18,17 @@
/* XXX WARNING: This code compiles, but is functionally broken, and
* currently not used by the rest of GeglBuffer */
+
+#include <glib-object.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+#include "gegl-types.h"
+#include "gegl-buffer-private.h"
#include "gegl-sampler-lanczos.h"
-#include "gegl-buffer-private.h" /* XXX */
#include <string.h>
#include <math.h>
+
enum
{
PROP_0,
@@ -31,86 +37,42 @@
PROP_LAST
};
-static void
-get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
-
- switch (prop_id)
- {
- case PROP_LANCZOS_WIDTH:
- g_value_set_int (value, self->lanczos_width);
- break;
-
- case PROP_LANCZOS_SAMPLES:
- g_value_set_int (value, self->lanczos_spp);
- break;
-
- default:
- break;
- }
-}
-
-static void
-set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
-
- switch (prop_id)
- {
- case PROP_LANCZOS_WIDTH:
- self->lanczos_width = g_value_get_int (value);
- break;
-
- case PROP_LANCZOS_SAMPLES:
- self->lanczos_spp = g_value_get_int (value);
- break;
-
- default:
- break;
- }
-}
-
-static void gegl_sampler_lanczos_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
-
-static void gegl_sampler_lanczos_prepare (GeglSampler *self);
-
static inline gdouble sinc (gdouble x);
-static void lanczos_lookup (GeglSampler *sampler);
+static void lanczos_lookup (GeglSamplerLanczos *sampler);
+static void gegl_sampler_lanczos_get (GeglSampler *sampler,
+ gdouble x,
+ gdouble y,
+ void *output);
+static void get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static GObject *
+gegl_sampler_lanczos_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params);
+static void finalize (GObject *object);
-G_DEFINE_TYPE (GeglSamplerLanczos, gegl_sampler_lanczos, GEGL_TYPE_SAMPLER)
-static void
-finalize (GObject *object)
-{
- GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
- GeglSampler *sampler = GEGL_SAMPLER (object);
+G_DEFINE_TYPE (GeglSamplerLanczos, gegl_sampler_lanczos, GEGL_TYPE_SAMPLER)
+static GObjectClass * parent_class = NULL;
- g_free (self->lanczos_lookup);
- g_free (sampler->cache_buffer);
- G_OBJECT_CLASS (gegl_sampler_lanczos_parent_class)->finalize (object);
-}
static void
gegl_sampler_lanczos_class_init (GeglSamplerLanczosClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
-
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ parent_class = g_type_class_peek_parent (klass);
object_class->finalize = finalize;
object_class->set_property = set_property;
object_class->get_property = get_property;
+ object_class->constructor = gegl_sampler_lanczos_constructor;
- sampler_class->prepare = gegl_sampler_lanczos_prepare;
sampler_class->get = gegl_sampler_lanczos_get;
g_object_class_install_property (object_class, PROP_LANCZOS_WIDTH,
@@ -136,115 +98,175 @@
static void
gegl_sampler_lanczos_init (GeglSamplerLanczos *self)
{
+
}
-void
-gegl_sampler_lanczos_prepare (GeglSampler *sampler)
+static GObject *
+gegl_sampler_lanczos_constructor (GType type,
+ guint n_params,
+ GObjectConstructParam *params)
{
- /*GeglBuffer *input = GEGL_BUFFER (sampler->input);*/
+ GObject *object;
+ GeglSamplerLanczos *self;
+ gint i;
+
+ object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+ self = GEGL_SAMPLER_LANCZOS (object);
+ for (i = 0; i < n_params; i++) {
+ if (!strcmp (params[i].pspec->name, "lanczos_spp"))
+ g_object_set(object, params[i].pspec->name, g_value_get_int (params[i].value), NULL);
+ if (!strcmp (params[i].pspec->name, "lanczos_width"))
+ g_object_set(object, params[i].pspec->name, g_value_get_int (params[i].value), NULL);
+ }
- /* calculate lookup */
- lanczos_lookup (sampler);
+ lanczos_lookup (self);
+ return object;
}
-void
-gegl_sampler_lanczos_get (GeglSampler *sampler,
- gdouble x,
- gdouble y,
- void *output)
+static void
+finalize (GObject *object)
{
- GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (sampler);
- GeglBuffer *buffer = sampler->buffer;
- gfloat *cache_buffer;
- gfloat *buf_ptr;
+ GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
+
+ if ( self->lanczos_lookup != NULL )
+ {
+ g_free (self->lanczos_lookup);
+ self->lanczos_lookup = NULL;
+ }
+
+ G_OBJECT_CLASS (gegl_sampler_lanczos_parent_class)->finalize (object);
+}
+void
+gegl_sampler_lanczos_get (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output)
+{
+ GeglSamplerLanczos *lanczos = GEGL_SAMPLER_LANCZOS (self);
+ GeglRectangle context_rect = self->context_rect;
+ gfloat *sampler_bptr;
gdouble x_sum, y_sum, arecip;
gdouble newval[4];
gfloat dst[4];
- gfloat abyss = 0.;
- gint i, j, pos, pu, pv;
- gint lanczos_spp = self->lanczos_spp;
- gint lanczos_width = self->lanczos_width;
- gint lanczos_width2 = lanczos_width * 2 + 1;
-
- gdouble x_kernel[lanczos_width2], /* 1-D kernels of Lanczos window coeffs */
- y_kernel[lanczos_width2];
-
- gegl_sampler_fill_buffer (sampler, x, y);
- cache_buffer = sampler->cache_buffer;
- if (!cache_buffer)
- return;
-
- if (x >= 0 &&
- y >= 0 &&
- x < buffer->extent.width &&
- y < buffer->extent.height)
+ gint i, j;
+ gint spp = lanczos->lanczos_spp;
+ gint width = lanczos->lanczos_width;
+ gint width2 = context_rect.width;
+ gint dx,dy;
+ gint u,v;
+
+ gdouble x_kernel[width2], /* 1-D kernels of Lanczos window coeffs */
+ y_kernel[width2];
+
+ self->interpolate_format = babl_format ("RaGaBaA float");
+
+ dx = (gint) ((x - ((gint) x)) * spp + 0.5);
+ dy = (gint) ((y - ((gint) y)) * spp + 0.5);
+ /* fill 1D kernels */
+ for (x_sum = y_sum = 0.0, i = width; i >= -width; i--)
{
- gint u = (gint) x;
- gint v = (gint) y;
- /* get weight for fractional error */
- gint su = (gint) ((x - u) * lanczos_spp + 0.5);
- gint sv = (gint) ((y - v) * lanczos_spp + 0.5);
- /* fill 1D kernels */
- for (x_sum = y_sum = 0.0, i = lanczos_width; i >= -lanczos_width; i--)
- {
- pos = i * lanczos_spp;
- x_sum += x_kernel[lanczos_width + i] = self->lanczos_lookup[ABS (su - pos)];
- y_sum += y_kernel[lanczos_width + i] = self->lanczos_lookup[ABS (sv - pos)];
- }
-
- /* normalise the weighted arrays */
- for (i = 0; i < lanczos_width2; i++)
- {
- x_kernel[i] /= x_sum;
- y_kernel[i] /= y_sum;
- }
+ gint pos = i * spp;
+ x_sum += x_kernel[width + i] = lanczos->lanczos_lookup[ABS (dx - pos)];
+ y_sum += y_kernel[width + i] = lanczos->lanczos_lookup[ABS (dy - pos)];
+ }
- newval[0] = newval[1] = newval[2] = newval[3] = 0.0;
- for (j = 0; j < lanczos_width2; j++)
- for (i = 0; i < lanczos_width2; i++)
- {
- pu = CLAMP (u + i - lanczos_width, 0, buffer->extent.width - 1);
- pv = CLAMP (v + j - lanczos_width, 0, buffer->extent.height - 1);
- buf_ptr = cache_buffer + ((pv * buffer->extent.width + pu) * 4);
- newval[0] += y_kernel[j] * x_kernel[i] * buf_ptr[0] * buf_ptr[3];
- newval[1] += y_kernel[j] * x_kernel[i] * buf_ptr[1] * buf_ptr[3];
- newval[2] += y_kernel[j] * x_kernel[i] * buf_ptr[2] * buf_ptr[3];
- newval[3] += y_kernel[j] * x_kernel[i] * buf_ptr[3];
- }
- if (newval[3] <= 0.0)
- {
- arecip = 0.0;
- newval[3] = 0;
- }
- else if (newval[3] > G_MAXDOUBLE)
- {
- arecip = 1.0 / newval[3];
- newval[3] = G_MAXDOUBLE;
- }
- else
- {
- arecip = 1.0 / newval[3];
- }
+ /* normalise the weighted arrays */
+ for (i = 0; i < width2; i++)
+ {
+ x_kernel[i] /= x_sum;
+ y_kernel[i] /= y_sum;
+ }
+ arecip = 0.0;
+ newval[0] = newval[1] = newval[2] = newval[3] = 0.0;
- dst[0] = CLAMP (newval[0] * arecip, 0, G_MAXDOUBLE);
- dst[1] = CLAMP (newval[1] * arecip, 0, G_MAXDOUBLE);
- dst[2] = CLAMP (newval[2] * arecip, 0, G_MAXDOUBLE);
- dst[3] = CLAMP (newval[3], 0, G_MAXDOUBLE);
+ dx = (gint) x;
+ dy = (gint) y;
+ for (v=dy+context_rect.y, j = 0; v < dy+context_rect.y+context_rect.height; j++, v++)
+ for (u=dx+context_rect.x, i = 0; u < dx+context_rect.x+context_rect.width; i++, u++)
+ {
+ sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);
+ newval[0] += y_kernel[j] * x_kernel[i] * sampler_bptr[0] * sampler_bptr[3];
+ newval[1] += y_kernel[j] * x_kernel[i] * sampler_bptr[1] * sampler_bptr[3];
+ newval[2] += y_kernel[j] * x_kernel[i] * sampler_bptr[2] * sampler_bptr[3];
+ newval[3] += y_kernel[j] * x_kernel[i] * sampler_bptr[3];
+ }
+ if (newval[3] <= 0.0)
+ {
+ arecip = 0.0;
+ newval[3] = 0;
+ }
+ else if (newval[3] > G_MAXDOUBLE)
+ {
+ arecip = 1.0 / newval[3];
+ newval[3] = G_MAXDOUBLE;
}
else
{
- dst[0] = abyss;
- dst[1] = abyss;
- dst[2] = abyss;
- dst[3] = abyss;
+ arecip = 1.0 / newval[3];
}
- babl_process (babl_fish (sampler->interpolate_format, sampler->format),
+
+ dst[0] = CLAMP (newval[0] * arecip, 0, G_MAXDOUBLE);
+ dst[1] = CLAMP (newval[1] * arecip, 0, G_MAXDOUBLE);
+ dst[2] = CLAMP (newval[2] * arecip, 0, G_MAXDOUBLE);
+ dst[3] = CLAMP (newval[3], 0, G_MAXDOUBLE);
+
+ babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
}
+static void
+get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
+
+ switch (prop_id)
+ {
+ case PROP_LANCZOS_WIDTH:
+ g_value_set_int (value, self->lanczos_width);
+ break;
+
+ case PROP_LANCZOS_SAMPLES:
+ g_value_set_int (value, self->lanczos_spp);
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void
+set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (object);
+
+ switch (prop_id)
+ {
+ case PROP_LANCZOS_WIDTH:
+ {
+ self->lanczos_width = g_value_get_int (value);
+ GEGL_SAMPLER (self)->context_rect.x = - self->lanczos_width;
+ GEGL_SAMPLER (self)->context_rect.y = - self->lanczos_width;
+ GEGL_SAMPLER (self)->context_rect.width = self->lanczos_width*2+1;
+ GEGL_SAMPLER (self)->context_rect.height = self->lanczos_width*2+1;
+ }
+ break;
+ case PROP_LANCZOS_SAMPLES:
+ self->lanczos_spp = g_value_get_int (value);
+ break;
+
+ default:
+ break;
+ }
+}
/* Internal lanczos */
@@ -260,14 +282,13 @@
}
static void
-lanczos_lookup (GeglSampler *sampler)
+lanczos_lookup (GeglSamplerLanczos *sampler)
{
GeglSamplerLanczos *self = GEGL_SAMPLER_LANCZOS (sampler);
const gint lanczos_width = self->lanczos_width;
const gint samples = (self->lanczos_spp * (lanczos_width + 1));
const gdouble dx = (gdouble) lanczos_width / (gdouble) (samples - 1);
-
gdouble x = 0.0;
gint i;
Modified: trunk/gegl/buffer/gegl-sampler-linear.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-linear.c (original)
+++ trunk/gegl/buffer/gegl-sampler-linear.c Sat Jun 14 13:25:17 2008
@@ -14,28 +14,36 @@
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
*
*/
-#include "gegl-sampler-linear.h"
+
+
+#include <glib-object.h>
+#include <glib/gstdio.h>
+#include <glib/gprintf.h>
+#include "gegl-types.h"
#include "gegl-buffer-private.h"
+#include "gegl-sampler-linear.h"
#include <string.h>
+#include <math.h>
+
+
enum
{
PROP_0,
- PROP_CONTEXT_PIXELS,
PROP_LAST
};
-static void gegl_sampler_linear_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
+static void gegl_sampler_linear_get (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output);
static void set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
-static void get_property (GObject *gobject,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
+static void get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
G_DEFINE_TYPE (GeglSamplerLinear, gegl_sampler_linear, GEGL_TYPE_SAMPLER)
@@ -50,99 +58,73 @@
object_class->get_property = get_property;
sampler_class->get = gegl_sampler_linear_get;
-
- g_object_class_install_property (object_class, PROP_CONTEXT_PIXELS,
- g_param_spec_int ("context-pixels",
- "ContextPixels",
- "number of neighbourhood pixels needed in each direction",
- 0, 16, 1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-
}
static void
gegl_sampler_linear_init (GeglSamplerLinear *self)
{
- GEGL_SAMPLER (self)->context_pixels=1;
+ GEGL_SAMPLER (self)->context_rect = (GeglRectangle){ 0, 0, 2, 2};
+ GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
void
-gegl_sampler_linear_get (GeglSampler *sampler,
- gdouble x,
- gdouble y,
- void *output)
-{
- GeglRectangle *rect;
- gfloat *cache_buffer;
- gfloat dst[4];
- gfloat abyss = 0.;
-
- gegl_sampler_fill_buffer (sampler, x, y);
- rect = &sampler->cache_rectangle;
- cache_buffer = sampler->cache_buffer;
- if (!cache_buffer)
- return;
-
- if (x >= rect->x &&
- y >= rect->y &&
- x < rect->x+rect->width &&
- y < rect->y+rect->height)
+gegl_sampler_linear_get (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output)
+{
+ GeglRectangle context_rect = self->context_rect;
+ gfloat *sampler_bptr;
+ gfloat abyss = 0.;
+ gfloat dst[4];
+ gdouble arecip;
+ gdouble newval[4];
+ gdouble q[4];
+ gdouble dx,dy;
+ gdouble uf, vf;
+ gint u,v;
+ gint i;
+
+
+ uf = x - (gint) x;
+ vf = y - (gint) y;
+
+ q[0] = (1 - uf) * (1 - vf);
+ q[1] = uf * (1 - vf);
+ q[2] = (1 - uf) * vf;
+ q[3] = uf * vf;
+ dx = (gint) x;
+ dy = (gint) y;
+ newval[0] = newval[1] = newval[2] = newval[3] = 0.;
+ for (i=0, v=dy+context_rect.y; v < dy+context_rect.height ; v++)
+ for (u=dx+context_rect.x; u < dx+context_rect.width ; u++, i++)
+ {
+ sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);
+ newval[0] += q[i] * sampler_bptr[0] * sampler_bptr[3];
+ newval[1] += q[i] * sampler_bptr[1] * sampler_bptr[3];
+ newval[2] += q[i] * sampler_bptr[2] * sampler_bptr[3];
+ newval[3] += q[i] * sampler_bptr[3];
+ }
+
+ if (newval[3] <= abyss)
{
- gint i;
- gint x0;
- gint y0;
- gint x1;
- gint y1;
- gint u;
- gint v;
- gdouble uf;
- gdouble vf;
- gdouble q1;
- gdouble q2;
- gdouble q3;
- gdouble q4;
- gfloat * p00;
- gfloat * p01;
- gfloat * p10;
- gfloat * p11;
- x -= rect->x;
- y -= rect->y;
- x0 = 0;
- y0 = 0;
- x1 = rect->width - 1;
- y1 = rect->height - 1;
- u = (gint) x;
- v = (gint) y;
- uf = x - u;
- vf = y - v;
- q1 = (1 - uf) * (1 - vf);
- q2 = uf * (1 - vf);
- q3 = (1 - uf) * vf;
- q4 = uf * vf;
- p00 = cache_buffer + (v * rect->width + u) * 4;
- u = CLAMP ((gint) x + 0, x0, x1);
- v = CLAMP ((gint) y + 1, y0, y1);
- p01 = cache_buffer + (v * rect->width + u) * 4;
- u = CLAMP ((gint) x + 1, x0, x1);
- v = CLAMP ((gint) y + 0, y0, y1);
- p10 = cache_buffer + (v * rect->width + u) * 4;
- u = CLAMP ((gint) x + 1, x0, x1);
- v = CLAMP ((gint) y + 1, y0, y1);
- p11 = cache_buffer + (v * rect->width + u) * 4;
- for (i = 0; i < 4; i++)
- {
- dst[i] = q1 * p00[i] + q2 * p10[i] + q3 * p01[i] + q4 * p11[i];
- }
+ arecip = abyss;
+ newval[3] = abyss;
+ }
+ else if (newval[3] > G_MAXDOUBLE)
+ {
+ arecip = 1.0 / newval[3];
+ newval[3] = G_MAXDOUBLE;
}
else
{
- dst[0] = abyss;
- dst[1] = abyss;
- dst[2] = abyss;
- dst[3] = abyss;
+ arecip = 1.0 / newval[3];
}
- babl_process (babl_fish (sampler->interpolate_format, sampler->format),
+ dst[0] = CLAMP (newval[0] * arecip, 0, G_MAXDOUBLE);
+ dst[1] = CLAMP (newval[1] * arecip, 0, G_MAXDOUBLE);
+ dst[2] = CLAMP (newval[2] * arecip, 0, G_MAXDOUBLE);
+ dst[3] = CLAMP (newval[3], 0, G_MAXDOUBLE);
+ babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
}
@@ -156,9 +138,6 @@
{
switch (property_id)
{
- case PROP_CONTEXT_PIXELS:
- g_object_set_property (gobject, "GeglSampler::context-pixels", value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
@@ -174,9 +153,6 @@
{
switch (property_id)
{
- case PROP_CONTEXT_PIXELS:
- g_object_get_property (gobject, "GeglSampler::context-pixels", value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
Modified: trunk/gegl/buffer/gegl-sampler-nearest.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler-nearest.c (original)
+++ trunk/gegl/buffer/gegl-sampler-nearest.c Sat Jun 14 13:25:17 2008
@@ -14,15 +14,31 @@
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
*
*/
-#include "gegl-sampler-nearest.h"
+
+#include <glib-object.h>
+#include "gegl-types.h"
#include "gegl-buffer-private.h"
+#include "gegl-sampler-nearest.h"
#include <string.h>
-static void gegl_sampler_nearest_get (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
-
+enum
+{
+ PROP_0,
+ PROP_LAST
+};
+
+static void gegl_sampler_nearest_get (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output);
+static void set_property (GObject *gobject,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void get_property (GObject *gobject,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
G_DEFINE_TYPE (GeglSamplerNearest, gegl_sampler_nearest, GEGL_TYPE_SAMPLER)
@@ -30,6 +46,10 @@
gegl_sampler_nearest_class_init (GeglSamplerNearestClass *klass)
{
GeglSamplerClass *sampler_class = GEGL_SAMPLER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
sampler_class->get = gegl_sampler_nearest_get;
@@ -38,6 +58,8 @@
static void
gegl_sampler_nearest_init (GeglSamplerNearest *self)
{
+ GEGL_SAMPLER (self)->context_rect = (GeglRectangle){0,0,1,1};
+ GEGL_SAMPLER (self)->interpolate_format = babl_format ("RaGaBaA float");
}
void
@@ -46,37 +68,35 @@
gdouble y,
void *output)
{
- gfloat * cache_buffer;
- GeglRectangle * rect;
- gint u;
- gint v;
- gfloat dst[4];
-
- gegl_sampler_fill_buffer (self, x, y);
-
- rect = &self->cache_rectangle;
- cache_buffer = self->cache_buffer;
- if (!cache_buffer)
- return;
- u = (x - rect->x);
- v = (y - rect->y);
-
- if (u >= 0 &&
- v >= 0 &&
- u < rect->width &&
- v < rect->height)
+ gfloat *sampler_bptr;
+ sampler_bptr = gegl_sampler_get_from_buffer (self, (gint)x, (gint)y);
+ babl_process (babl_fish (self->interpolate_format, self->format), sampler_bptr, output, 1);
+}
+
+static void
+set_property (GObject *gobject,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
{
- gint pos = (v * rect->width + u) * 4;
- memcpy (dst, cache_buffer + pos, sizeof (gfloat) * 4);
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
+ break;
}
- else
+}
+
+static void
+get_property (GObject *gobject,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ switch (property_id)
{
- dst[0] = 0.0;
- dst[1] = 0.0;
- dst[2] = 0.0;
- dst[3] = 0.0;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
+ break;
}
- babl_process (babl_fish (self->interpolate_format, self->format),
- dst, output, 1);
}
-
Modified: trunk/gegl/buffer/gegl-sampler.c
==============================================================================
--- trunk/gegl/buffer/gegl-sampler.c (original)
+++ trunk/gegl/buffer/gegl-sampler.c Sat Jun 14 13:25:17 2008
@@ -15,26 +15,31 @@
*
* 2007 Â Ãyvind KolÃs
*/
-
-#define SIZE 16 /* the cached region around a fetched pixel value is
- SIZEÃSIZE pixels. */
-
#include "config.h"
#include <glib-object.h>
#include <string.h>
#include "gegl-types.h"
-#include "gegl-sampler.h"
+#include "gegl-buffer.h"
#include "gegl-utils.h"
#include "gegl-buffer-private.h"
+#include "gegl-sampler-nearest.h"
+#include "gegl-sampler-linear.h"
+#include "gegl-sampler-cubic.h"
+#include "gegl-sampler-lanczos.h"
+
+#if ENABLE_MP
+GStaticRecMutex mutex = G_STATIC_REC_MUTEX_INIT;
+#endif
+
enum
{
PROP_0,
PROP_BUFFER,
PROP_FORMAT,
- PROP_CONTEXT_PIXELS,
+ PROP_CONTEXT_RECT,
PROP_LAST
};
@@ -50,6 +55,8 @@
guint prop_id,
const GValue *value,
GParamSpec *pspec);
+static void set_buffer (GeglSampler *self,
+ GeglBuffer *buffer);
G_DEFINE_TYPE (GeglSampler, gegl_sampler, G_TYPE_OBJECT)
@@ -63,16 +70,11 @@
klass->prepare = NULL;
klass->get = NULL;
+ klass->set_buffer = set_buffer;
object_class->set_property = set_property;
object_class->get_property = get_property;
- g_object_class_install_property (object_class, PROP_BUFFER,
- g_param_spec_object ("buffer",
- "Buffer",
- "Input pad, for image buffer input.",
- GEGL_TYPE_BUFFER,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class, PROP_FORMAT,
g_param_spec_pointer ("format",
@@ -80,21 +82,23 @@
"babl format",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property (object_class, PROP_CONTEXT_PIXELS,
- g_param_spec_int ("context-pixels",
- "ContextPixels",
- "number of neighbourhood pixels needed in each direction",
- 0, 16, 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
+ g_object_class_install_property (object_class, PROP_BUFFER,
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "Input pad, for image buffer input.",
+ GEGL_TYPE_BUFFER,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
}
static void
gegl_sampler_init (GeglSampler *self)
{
- self->cache_buffer = NULL;
+ GeglRectangle context_rect = {0,0,1,1};
+ GeglRectangle sampler_rectangle = {0,0,0,0};
+ self->sampler_buffer = NULL;
self->buffer = NULL;
- self->context_pixels = 0;
+ self->context_rect = context_rect;
+ self->sampler_rectangle = sampler_rectangle;
}
void
@@ -135,14 +139,28 @@
#endif
}
+void
+gegl_sampler_set_buffer (GeglSampler *self, GeglBuffer *buffer)
+{
+ GeglSamplerClass *klass;
+
+ g_return_if_fail (GEGL_IS_SAMPLER (self));
+
+ klass = GEGL_SAMPLER_GET_CLASS (self);
+
+ if (klass->set_buffer)
+ klass->set_buffer (self, buffer);
+}
+
+
static void
finalize (GObject *gobject)
{
GeglSampler *sampler = GEGL_SAMPLER (gobject);
- if (sampler->cache_buffer)
+ if (sampler->sampler_buffer)
{
- g_free (sampler->cache_buffer);
- sampler->cache_buffer = NULL;
+ g_free (sampler->sampler_buffer);
+ sampler->sampler_buffer = NULL;
}
G_OBJECT_CLASS (gegl_sampler_parent_class)->finalize (gobject);
}
@@ -159,50 +177,45 @@
G_OBJECT_CLASS (gegl_sampler_parent_class)->dispose (gobject);
}
-void
-gegl_sampler_fill_buffer (GeglSampler *sampler,
- gdouble x,
- gdouble y)
-{
- GeglBuffer *buffer;
- GeglRectangle surround;
-
- buffer = sampler->buffer;
- g_assert (buffer);
-
- if (sampler->cache_buffer)
- {
- GeglRectangle r = sampler->cache_rectangle;
-
- /* check if the cache-buffer includes both the desired coordinates and
- * a sufficient surrounding context
- */
- if (x - r.x >= sampler->context_pixels &&
- x - r.x < r.width - sampler->context_pixels &&
- y - r.y >= sampler->context_pixels &&
- y - r.y < r.height - sampler->context_pixels)
- {
- return; /* we can reuse our cached interpolation source buffer */
- }
-
- g_free (sampler->cache_buffer);
- sampler->cache_buffer = NULL;
- }
-
- surround.x = x - SIZE/2;
- surround.y = y - SIZE/2;
- surround.width = SIZE;
- surround.height = SIZE;
-
- sampler->cache_buffer = g_malloc0 (surround.width *
- surround.height *
- 4 * sizeof (gfloat));
- sampler->cache_rectangle = surround;
- sampler->interpolate_format = babl_format ("RaGaBaA float");
-
- gegl_buffer_get (buffer, 1.0, &surround,
- sampler->interpolate_format,
- sampler->cache_buffer, GEGL_AUTO_ROWSTRIDE);
+gfloat *
+gegl_sampler_get_from_buffer (GeglSampler *sampler,
+ gint x,
+ gint y)
+{
+ const GeglRectangle *buffer_rectangle;
+ guchar *buffer_ptr;
+ gint dx;
+ gint dy;
+ gint bpp;
+ gint sof;
+
+ /* Initialise */
+ bpp = sampler->interpolate_format->format.bytes_per_pixel;
+ buffer_rectangle = gegl_buffer_get_extent(sampler->buffer);
+ if ( !gegl_rectangle_contains (buffer_rectangle, &sampler->sampler_rectangle) ||
+ sampler->sampler_buffer == NULL )
+ {
+ gint buffer_size = (buffer_rectangle->width *
+ buffer_rectangle->height *
+ bpp);
+ if ( sampler->sampler_buffer == NULL )
+ sampler->sampler_buffer = g_malloc0 (buffer_size);
+ else
+ sampler->sampler_buffer = g_realloc (sampler->sampler_buffer, buffer_size);
+ gegl_buffer_get (sampler->buffer,
+ 1.0,
+ buffer_rectangle,
+ sampler->interpolate_format,
+ sampler->sampler_buffer,
+ GEGL_AUTO_ROWSTRIDE);
+ gegl_rectangle_copy (&sampler->sampler_rectangle,buffer_rectangle);
+ }
+
+ dx = x - buffer_rectangle->x;
+ dy = y - buffer_rectangle->y;
+ buffer_ptr = (guchar *)sampler->sampler_buffer;
+ sof = ( dx + (dy * buffer_rectangle->width)) * bpp;
+ return (gfloat*)(buffer_ptr+sof);
}
static void
@@ -223,10 +236,6 @@
g_value_set_pointer (value, self->format);
break;
- case PROP_CONTEXT_PIXELS:
- g_value_set_int (value, self->context_pixels);
- break;
-
default:
break;
}
@@ -250,11 +259,64 @@
self->format = g_value_get_pointer (value);
break;
- case PROP_CONTEXT_PIXELS:
- self->context_pixels = g_value_get_int (value);
- break;
-
default:
break;
}
}
+
+
+static void
+set_buffer (GeglSampler *self, GeglBuffer *buffer)
+{
+ if (self->buffer != buffer)
+ {
+ if (GEGL_IS_BUFFER(self->buffer))
+ g_object_unref(self->buffer);
+ if (GEGL_IS_BUFFER (buffer))
+ self->buffer = gegl_buffer_dup (buffer);
+ else
+ self->buffer = NULL;
+ }
+}
+
+GeglInterpolation
+gegl_buffer_interpolation_from_string (const gchar *string)
+{
+ if (g_str_equal (string, "nearest") ||
+ g_str_equal (string, "none"))
+ return GEGL_INTERPOLATION_NEAREST;
+
+ if (g_str_equal (string, "linear") ||
+ g_str_equal (string, "bilinear"))
+ return GEGL_INTERPOLATION_LINEAR;
+
+ if (g_str_equal (string, "cubic") ||
+ g_str_equal (string, "bicubic"))
+ return GEGL_INTERPOLATION_CUBIC;
+
+ if (g_str_equal (string, "lanczos"))
+ return GEGL_INTERPOLATION_LANCZOS;
+
+ return GEGL_INTERPOLATION_NEAREST;
+}
+
+
+GType
+gegl_sampler_type_from_interpolation (GeglInterpolation interpolation)
+{
+ switch (interpolation)
+ {
+ case GEGL_INTERPOLATION_NEAREST:
+ return GEGL_TYPE_SAMPLER_NEAREST;
+ case GEGL_INTERPOLATION_LINEAR:
+ return GEGL_TYPE_SAMPLER_LINEAR;
+#if 0 /* disabled for now */
+ case GEGL_INTERPOLATION_CUBIC:
+ return GEGL_TYPE_SAMPLER_CUBIC;
+ case GEGL_INTERPOLATION_LANCZOS:
+ return GEGL_TYPE_SAMPLER_LANCZOS;
+#endif
+ default:
+ return GEGL_TYPE_SAMPLER_LINEAR;
+ }
+}
Modified: trunk/gegl/buffer/gegl-sampler.h
==============================================================================
--- trunk/gegl/buffer/gegl-sampler.h (original)
+++ trunk/gegl/buffer/gegl-sampler.h Sat Jun 14 13:25:17 2008
@@ -20,8 +20,8 @@
#include <glib-object.h>
#include <babl/babl.h>
-#include "gegl-types.h"
-#include "buffer/gegl-buffer-types.h"
+
+/* this file needs to be included by gegl-buffer-private */
G_BEGIN_DECLS
@@ -33,6 +33,7 @@
#define GEGL_SAMPLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEGL_TYPE_SAMPLER, GeglSamplerClass))
typedef struct _GeglSamplerClass GeglSamplerClass;
+typedef struct _GeglSampler GeglSampler;
struct _GeglSampler
{
@@ -41,22 +42,24 @@
/*< private >*/
GeglBuffer *buffer;
Babl *format;
-
- GeglRectangle cache_rectangle;
- void *cache_buffer;
Babl *interpolate_format;
- gint context_pixels;
+ GeglRectangle context_rect;
+ void *sampler_buffer;
+ GeglRectangle sampler_rectangle;
+
};
struct _GeglSamplerClass
{
GObjectClass parent_class;
- void (* prepare) (GeglSampler *self);
- void (* get) (GeglSampler *self,
- gdouble x,
- gdouble y,
- void *output);
+ void (* prepare) (GeglSampler *self);
+ void (* get) (GeglSampler *self,
+ gdouble x,
+ gdouble y,
+ void *output);
+ void (*set_buffer) (GeglSampler *self,
+ GeglBuffer *buffer);
};
GType gegl_sampler_get_type (void) G_GNUC_CONST;
@@ -67,10 +70,13 @@
gdouble x,
gdouble y,
void *output);
+void gegl_sampler_set_buffer (GeglSampler *self,
+ GeglBuffer *buffer);
+
+gfloat * gegl_sampler_get_from_buffer (GeglSampler *sampler,
+ gint x,
+ gint y);
-void gegl_sampler_fill_buffer (GeglSampler *sampler,
- gdouble x,
- gdouble y);
G_END_DECLS
Modified: trunk/operations/affine/affine.c
==============================================================================
--- trunk/operations/affine/affine.c (original)
+++ trunk/operations/affine/affine.c Sat Jun 14 13:25:17 2008
@@ -25,10 +25,11 @@
#include <math.h>
#include <gegl-plugin.h>
+#include "buffer/gegl-sampler.h"
#include <graph/gegl-pad.h>
#include <graph/gegl-node.h>
#include <graph/gegl-connection.h>
-/*#include "buffer/gegl-sampler.h"*/
+
#include "affine.h"
#include "module.h"
@@ -118,19 +119,74 @@
return g_define_type_id;
}
+
+GType
+gegl_sampler_type_from_interpolation (GeglInterpolation interpolation);
+
/* ************************* */
+static void
+op_affine_sampler_init (OpAffine *self)
+{
+ Babl *format;
+ GeglSampler *sampler;
+ GType desired_type;
+ GeglInterpolation interpolation;
+
+ format = babl_format ("RaGaBaA float");
+
+ interpolation = gegl_buffer_interpolation_from_string (self->filter);
+ desired_type = gegl_sampler_type_from_interpolation (interpolation);
+
+ if (self->sampler != NULL &&
+ !G_TYPE_CHECK_INSTANCE_TYPE (self->sampler, desired_type))
+ {
+ self->sampler->buffer=NULL;
+ g_object_unref(self->sampler);
+ self->sampler = NULL;
+ }
+
+ if (self->sampler == NULL)
+ {
+ if (interpolation == GEGL_INTERPOLATION_LANCZOS)
+ {
+ sampler = g_object_new (desired_type,
+ "format", format,
+ "lanczos_width", self->lanczos_width,
+ NULL);
+ }
+ else
+ {
+ sampler = g_object_new (desired_type,
+ "format", format,
+ NULL);
+ }
+ self->sampler = g_object_ref(sampler);
+ }
+}
static void
prepare (GeglOperation *operation)
{
- Babl *format = babl_format ("RaGaBaA float");
-
+ OpAffine *affine = (OpAffine *) operation;
+ Babl *format = babl_format ("RaGaBaA float");
+ op_affine_sampler_init (affine);
/*gegl_operation_set_format (operation, "input", format);
gegl_operation_set_format (operation, "aux", format); XXX(not used yet) */
gegl_operation_set_format (operation, "output", format);
}
static void
+finalize (GObject *object)
+{
+ OpAffine *affine = (OpAffine *) object;
+ if (affine->sampler != NULL)
+ {
+ g_object_unref(affine->sampler);
+ affine->sampler = NULL;
+ }
+}
+
+static void
op_affine_class_init (OpAffineClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
@@ -139,6 +195,7 @@
gobject_class->set_property = set_property;
gobject_class->get_property = get_property;
+ gobject_class->finalize = finalize;
op_class->get_invalidated_by_change = get_invalidated_by_change;
op_class->get_bounding_box = get_bounding_box;
@@ -147,6 +204,7 @@
op_class->categories = "transform";
op_class->prepare = prepare;
+
filter_class->process = process;
klass->create_matrix = NULL;
@@ -171,7 +229,7 @@
g_param_spec_string (
"filter",
"Filter",
- "Filter type (nearest, linear, lanczos)",
+ "Filter type (nearest, linear, lanczos, cubic)",
"linear",
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
g_object_class_install_property (gobject_class, PROP_HARD_EDGES,
@@ -190,6 +248,7 @@
G_PARAM_CONSTRUCT | G_PARAM_READWRITE));
}
+
static void
op_affine_init (OpAffine *self)
{
@@ -370,8 +429,15 @@
gdouble have_points [8];
gint i;
+ GeglRectangle context_rect;
+ GeglSampler *sampler;
+
+ sampler = affine->sampler;
+ context_rect = sampler->context_rect;
+
+
if (gegl_operation_source_get_bounding_box (op, "input"))
- in_rect = *gegl_operation_source_get_bounding_box (op, "input");
+ in_rect = *gegl_operation_source_get_bounding_box (op, "input");
/* invoke child's matrix creation function */
g_assert (klass->create_matrix);
@@ -394,21 +460,10 @@
return in_rect;
}
- if (! strcmp (affine->filter, "linear"))
- {
- if (affine->hard_edges)
- {
- in_rect.width ++;
- in_rect.height ++;
- }
- else
- {
- in_rect.x--;
- in_rect.y--;
- in_rect.width += 2;
- in_rect.height += 2;
- }
- }
+ in_rect.x += context_rect.x;
+ in_rect.y += context_rect.y;
+ in_rect.width += context_rect.width;
+ in_rect.height += context_rect.height;
have_points [0] = in_rect.x;
have_points [1] = in_rect.y;
@@ -427,7 +482,6 @@
have_points + i, have_points + i + 1);
bounding_box (have_points, 4, &have_rect);
-
return have_rect;
}
@@ -472,10 +526,14 @@
Matrix3 inverse;
GeglRectangle requested_rect,
need_rect;
+ GeglRectangle context_rect;
+ GeglSampler *sampler;
gdouble need_points [8];
gint i;
requested_rect = *region;
+ sampler = affine->sampler;
+ context_rect = sampler->context_rect;
matrix3_copy (inverse, affine->matrix);
matrix3_invert (inverse);
@@ -506,22 +564,10 @@
need_points + i, need_points + i + 1);
bounding_box (need_points, 4, &need_rect);
- if (! strcmp (affine->filter, "linear"))
- {
- if (affine->hard_edges)
- {
- need_rect.width ++;
- need_rect.height ++;
- }
- else
- {
- need_rect.x--;
- need_rect.y--;
- need_rect.width += 2;
- need_rect.height += 2;
- }
- }
-
+ need_rect.x += context_rect.x;
+ need_rect.y += context_rect.y;
+ need_rect.width += context_rect.width;
+ need_rect.height += context_rect.height;
return need_rect;
}
@@ -530,13 +576,18 @@
const gchar *input_pad,
const GeglRectangle *input_region)
{
- OpAffine *affine = (OpAffine *) op;
- OpAffineClass *klass = OP_AFFINE_GET_CLASS (affine);
- GeglRectangle affected_rect;
- gdouble affected_points [8];
- gint i;
- GeglRectangle region = *input_region;
-
+ OpAffine *affine = (OpAffine *) op;
+ OpAffineClass *klass = OP_AFFINE_GET_CLASS (affine);
+ GeglRectangle affected_rect;
+ GeglRectangle context_rect;
+ GeglSampler *sampler;
+ gdouble affected_points [8];
+ gint i;
+ GeglRectangle region = *input_region;
+
+ op_affine_sampler_init (affine);
+ sampler = affine->sampler;
+ context_rect = sampler->context_rect;
/* invoke child's matrix creation function */
g_assert (klass->create_matrix);
matrix3_identity (affine->matrix);
@@ -558,21 +609,10 @@
return region;
}
- if (! strcmp (affine->filter, "linear"))
- {
- if (affine->hard_edges)
- {
- region.width ++;
- region.height ++;
- }
- else
- {
- region.x--;
- region.y--;
- region.width += 2;
- region.height += 2;
- }
- }
+ region.x += context_rect.x;
+ region.y += context_rect.y;
+ region.width += context_rect.width;
+ region.height += context_rect.height;
affected_points [0] = region.x;
affected_points [1] = region.y;
@@ -591,7 +631,6 @@
affected_points + i, affected_points + i + 1);
bounding_box (affected_points, 4, &affected_rect);
-
return affected_rect;
}
@@ -605,7 +644,7 @@
affine_generic (GeglBuffer *dest,
GeglBuffer *src,
Matrix3 matrix,
- GeglInterpolation interpolation)
+ GeglSampler *sampler)
{
const GeglRectangle *dest_extent;
gint x, y;
@@ -640,17 +679,12 @@
v_start = inverse[1][0] * dest_extent->x + inverse[1][1] * dest_extent->y
+ inverse[1][2];
- /* correct rounding on e.g. negative scaling (is this sound?) */
+ /* correct rounding on e.g. negative scaling (is this sound?) */
if (inverse [0][0] < 0.)
u_start -= .001;
if (inverse [1][1] < 0.)
v_start -= .001;
- if (src->sampler)
- {
- gegl_sampler_prepare (src->sampler);
- }
-
for (dest_ptr = dest_buf, y = dest_extent->height; y--;)
{
u_float = u_start;
@@ -658,13 +692,9 @@
for (x = dest_extent->width; x--;)
{
- gfloat pix[4];
- gegl_buffer_sample (src, u_float, v_float, 1.0, pix, format, interpolation);
+ gegl_sampler_get (sampler, u_float, v_float, dest_ptr);
- *dest_ptr++ = pix[0];
- *dest_ptr++ = pix[1];
- *dest_ptr++ = pix[2];
- *dest_ptr++ = pix[3];
+ dest_ptr+=4;
u_float += inverse [0][0];
v_float += inverse [1][0];
@@ -672,7 +702,7 @@
u_start += inverse [0][1];
v_start += inverse [1][1];
}
- gegl_buffer_sample_cleanup (src);
+
gegl_buffer_set (dest, NULL, format, dest_buf, GEGL_AUTO_ROWSTRIDE);
g_free (dest_buf);
}
@@ -687,11 +717,6 @@
{
OpAffine *affine = (OpAffine *) operation;
- /*g_warning ("%i,%i %ix%i | %i,%i %ix%i | %i,%i %ix%i",
- input->x, input->y, input->width, input->height,
- output->x, output->y, output->width, output->height,
- result->x, result->y, result->width, result->height);*/
-
if (is_intermediate_node (affine) ||
matrix3_is_identity (affine->matrix))
{
@@ -726,9 +751,12 @@
else
{
/* XXX: add back more samplers */
- affine_generic (output, input, affine->matrix,
- gegl_buffer_interpolation_from_string (affine->filter));
+ g_object_set(affine->sampler, "buffer", input, NULL);
+ affine_generic (output, input, affine->matrix, affine->sampler);
+ g_object_unref(affine->sampler->buffer);
+ affine->sampler->buffer = NULL;
}
return TRUE;
}
+
Modified: trunk/operations/affine/affine.h
==============================================================================
--- trunk/operations/affine/affine.h (original)
+++ trunk/operations/affine/affine.h Sat Jun 14 13:25:17 2008
@@ -2,6 +2,7 @@
#define __OP_AFFINE_H__
#include "matrix.h"
+#include "gegl-buffer-private.h"
G_BEGIN_DECLS
@@ -19,12 +20,13 @@
{
GeglOperationFilter parent;
- Matrix3 matrix;
- gdouble origin_x,
- origin_y;
- gchar *filter;
- gboolean hard_edges;
- gint lanczos_width;
+ Matrix3 matrix;
+ gdouble origin_x,
+ origin_y;
+ gchar *filter;
+ gboolean hard_edges;
+ gint lanczos_width;
+ GeglSampler *sampler;
};
typedef struct _OpAffineClass OpAffineClass;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]