Commit efb9d100 authored by Øyvind Kolås's avatar Øyvind Kolås

added a function used to prime a linear buffer with all needed samples for

* gegl/buffer/gegl-sampler.[ch]: (gegl_sampler_get_ptr): added a
function used to prime a linear buffer with all needed samples for
interpolation.
For all the interpolators, removed unneded alpha multiplications
(we're interpolating on premultiplied pixels), also moved linear and
cubic to skip unneeded function calls in innerloop.
* gegl/buffer/gegl-sampler-cubic.c:
* gegl/buffer/gegl-sampler-lanczos.c:
* gegl/buffer/gegl-sampler-linear.c:
* gegl/buffer/gegl-sampler-nearest.c:

svn path=/trunk/; revision=2489
parent 4417a2dc
2008-06-20 Øyvind Kolås <pippin@gimp.org>
* gegl/buffer/gegl-sampler.[ch]: (gegl_sampler_get_ptr): added a
function used to prime a linear buffer with all needed samples for
interpolation.
For all the interpolators, removed unneded alpha multiplications
(we're interpolating on premultiplied pixels), also moved linear and
cubic to skip unneeded function calls in innerloop.
* gegl/buffer/gegl-sampler-cubic.c:
* gegl/buffer/gegl-sampler-lanczos.c:
* gegl/buffer/gegl-sampler-linear.c:
* gegl/buffer/gegl-sampler-nearest.c:
2008-06-20 Øyvind Kolås <pippin@gimp.org>
* gegl/buffer/gegl-sampler.c: (gegl_sampler_prepare): reset the
......
......@@ -123,12 +123,13 @@ gegl_sampler_cubic_get (GeglSampler *self,
{
GeglSamplerCubic *cubic = (GeglSamplerCubic*)(self);
GeglRectangle context_rect;
const gint offsets[16]={-4-64*4, 4, 4, 4,
(64-3)*4, 4, 4, 4,
(64-3)*4, 4, 4, 4,
(64-3)*4, 4, 4, 4};
gfloat *sampler_bptr;
gfloat factor;
gdouble arecip;
gdouble newval[4];
gfloat abyss = 0.;
gfloat dst[4];
gfloat newval[4];
gint u,v;
gint dx,dy;
gint i;
......@@ -137,40 +138,22 @@ gegl_sampler_cubic_get (GeglSampler *self,
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_ptr (self, dx, dy);
for (v=dy+context_rect.y, i=0; v < dy+context_rect.y+context_rect.height ; v++)
for (u=dx+context_rect.x ; u < dx+context_rect.x+context_rect.width ; u++, i++)
{
sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);
/*sampler_bptr = gegl_sampler_get_from_buffer (self, u, v);*/
sampler_bptr += offsets[i];
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[0] += factor * sampler_bptr[0];
newval[1] += factor * sampler_bptr[1];
newval[2] += factor * sampler_bptr[2];
newval[3] += factor * sampler_bptr[3];
}
if (newval[3] <= abyss)
{
arecip = abyss;
newval[3] = abyss;
}
else if (newval[3] > G_MAXDOUBLE)
{
arecip = 1.0 / newval[3];
newval[3] = G_MAXDOUBLE;
}
else
{
arecip = 1.0 / newval[3];
}
for ( i=0 ; i < 3 ; i++ )
newval[i] *= arecip;
for ( i=0 ; i < 4 ; i++ )
dst[i] = CLAMP (newval[i], 0, G_MAXDOUBLE);
babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
newval, output, 1);
}
......@@ -230,7 +213,9 @@ cubicKernel (gfloat x,
gfloat c)
{
gfloat weight, x2, x3;
gfloat ax = (gfloat) fabs (x);
gfloat ax = x;
if (ax < 0.0)
ax *= -1.0;
if (ax > 2) return 0;
......@@ -247,6 +232,6 @@ cubicKernel (gfloat x,
(-12 * b - 48 * c) * ax +
(8 * b + 24 * c);
return weight * (1.0 / 6.0);
return weight / 6.0;
}
......@@ -146,10 +146,8 @@ gegl_sampler_lanczos_get (GeglSampler *self,
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];
gdouble x_sum, y_sum;
gfloat newval[4] = {0.0, 0.0, 0.0, 0.0};
gint i, j;
gint spp = lanczos->lanczos_spp;
gint width = lanczos->lanczos_width;
......@@ -157,7 +155,7 @@ gegl_sampler_lanczos_get (GeglSampler *self,
gint dx,dy;
gint u,v;
gdouble x_kernel[width2], /* 1-D kernels of Lanczos window coeffs */
gfloat x_kernel[width2], /* 1-D kernels of Lanczos window coeffs */
y_kernel[width2];
self->interpolate_format = babl_format ("RaGaBaA float");
......@@ -178,8 +176,6 @@ gegl_sampler_lanczos_get (GeglSampler *self,
x_kernel[i] /= x_sum;
y_kernel[i] /= y_sum;
}
arecip = 0.0;
newval[0] = newval[1] = newval[2] = newval[3] = 0.0;
dx = (gint) x;
dy = (gint) y;
......@@ -187,32 +183,14 @@ gegl_sampler_lanczos_get (GeglSampler *self,
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[0] += y_kernel[j] * x_kernel[i] * sampler_bptr[0];
newval[1] += y_kernel[j] * x_kernel[i] * sampler_bptr[1];
newval[2] += y_kernel[j] * x_kernel[i] * sampler_bptr[2];
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
{
arecip = 1.0 / newval[3];
}
for ( i=0 ; i < 3 ; i++ )
newval[i] *= arecip;
for ( i=0 ; i < 4 ; i++ )
dst[i] = CLAMP (newval[i], 0, G_MAXDOUBLE);
babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
newval, output, 1);
}
static void
......
......@@ -75,13 +75,12 @@ gegl_sampler_linear_get (GeglSampler *self,
{
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;
const gint offsets[4]={0, 4,
(64-1)*4, 4};
gfloat newval[4] = {0.0, 0.0, 0.0, 0.0};
gfloat q[4];
gfloat dx,dy;
gfloat uf, vf;
gint u,v;
gint i;
......@@ -95,38 +94,22 @@ gegl_sampler_linear_get (GeglSampler *self,
q[3] = uf * vf;
dx = (gint) x;
dy = (gint) y;
newval[0] = newval[1] = newval[2] = newval[3] = 0.;
sampler_bptr = gegl_sampler_get_ptr (self, dx, dy);
/* FIXME: unroll this loop */
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];
sampler_bptr += offsets[i];
newval[0] += q[i] * sampler_bptr[0];
newval[1] += q[i] * sampler_bptr[1];
newval[2] += q[i] * sampler_bptr[2];
newval[3] += q[i] * sampler_bptr[3];
}
if (newval[3] <= abyss)
{
arecip = abyss;
newval[3] = abyss;
}
else if (newval[3] > G_MAXDOUBLE)
{
arecip = 1.0 / newval[3];
newval[3] = G_MAXDOUBLE;
}
else
{
arecip = 1.0 / newval[3];
}
for ( i=0 ; i < 3 ; i++ )
newval[i] *= arecip;
for ( i=0 ; i < 4 ; i++ )
dst[i] = CLAMP (newval[i], 0, G_MAXDOUBLE);
babl_process (babl_fish (self->interpolate_format, self->format),
dst, output, 1);
newval, output, 1);
}
......
......@@ -59,7 +59,7 @@ 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");
GEGL_SAMPLER (self)->interpolate_format = babl_format ("RGBA float");
}
void
......
......@@ -185,6 +185,70 @@ dispose (GObject *gobject)
G_OBJECT_CLASS (gegl_sampler_parent_class)->dispose (gobject);
}
/* gets a pointer to the center pixel, within a buffer that has
* a rowstride of 64px * 16bpp
*/
gfloat *
gegl_sampler_get_ptr (GeglSampler *sampler,
gint x,
gint y)
{
guchar *buffer_ptr;
gint dx;
gint dy;
gint bpp;
gint sof;
bpp = sampler->interpolate_format->format.bytes_per_pixel;
if (sampler->sampler_buffer == NULL ||
x + sampler->context_rect.x < sampler->sampler_rectangle.x ||
y + sampler->context_rect.y < sampler->sampler_rectangle.y ||
x + sampler->context_rect.x + sampler->context_rect.width >= sampler->sampler_rectangle.x + sampler->sampler_rectangle.width ||
y + sampler->context_rect.y + sampler->context_rect.height >= sampler->sampler_rectangle.y + sampler->sampler_rectangle.height)
{
GeglRectangle fetch_rectangle/* = sampler->context_rect*/;
fetch_rectangle.x = x + sampler->context_rect.x;
fetch_rectangle.y = y + sampler->context_rect.y;
/* we override the fetch rectangle needed by the sampler, hoping that
* the extra pixels we fetch comes in useful in subsequent requests,
* we assume that it is more likely that further access is to the right
* or down of our currently requested position.
*/
fetch_rectangle.x -= 8;
fetch_rectangle.y -= 8;
fetch_rectangle.width = 64;
fetch_rectangle.height = 64;
if (sampler->sampler_buffer == NULL )
{ /* we always request the same amount of pixels (64kb worth) */
sampler->sampler_buffer = g_malloc0 (fetch_rectangle.width *
fetch_rectangle.height *
bpp);
}
gegl_buffer_get (sampler->buffer,
1.0,
&fetch_rectangle,
sampler->interpolate_format,
sampler->sampler_buffer,
GEGL_AUTO_ROWSTRIDE);
sampler->sampler_rectangle = fetch_rectangle;
}
dx = x - sampler->sampler_rectangle.x;
dy = y - sampler->sampler_rectangle.y;
buffer_ptr = (guchar *)sampler->sampler_buffer;
sof = ( dx + (dy * sampler->sampler_rectangle.width)) * bpp;
return (gfloat*)(buffer_ptr+sof);
}
#include <math.h>
gfloat *
......
......@@ -78,6 +78,10 @@ gfloat * gegl_sampler_get_from_buffer (GeglSampler *sampler,
gint x,
gint y);
gfloat *
gegl_sampler_get_ptr (GeglSampler *sampler,
gint x,
gint y);
GType gegl_sampler_type_from_interpolation (GeglInterpolation interpolation);
G_END_DECLS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment