|
Packit |
bc1512 |
/* This file is an image processing operation for GEGL
|
|
Packit |
bc1512 |
* GEGL is free software; you can redistribute it and/or
|
|
Packit |
bc1512 |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License as published by the Free Software Foundation; either
|
|
Packit |
bc1512 |
* version 3 of the License, or (at your option) any later version.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* GEGL is distributed in the hope that it will be useful,
|
|
Packit |
bc1512 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
bc1512 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
bc1512 |
* Lesser General Public License for more details.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
bc1512 |
* License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Copyright 2006 Dominik Ernst <dernst@gmx.de>
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* Recursive Gauss IIR Filter as described by Young / van Vliet
|
|
Packit |
bc1512 |
* in "Signal Processing 44 (1995) 139 - 151"
|
|
Packit |
bc1512 |
*
|
|
Packit |
bc1512 |
* NOTE: The IIR filter should not be used for radius < 0.5, since it
|
|
Packit |
bc1512 |
* becomes very inaccurate.
|
|
Packit |
bc1512 |
*/
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "config.h"
|
|
Packit |
bc1512 |
#include <glib/gi18n-lib.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#ifdef GEGL_CHANT_PROPERTIES
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_chant_double_ui (std_dev_x, _("Size X"), 0.0, 10000.0, 4.0, 0.0, 1000.0, 1.5,
|
|
Packit |
bc1512 |
_("Standard deviation for the horizontal axis. (multiply by ~2 to get radius)"))
|
|
Packit |
bc1512 |
gegl_chant_double_ui (std_dev_y, _("Size Y"), 0.0, 10000.0, 4.0, 0.0, 1000.0, 1.5,
|
|
Packit |
bc1512 |
_("Standard deviation for the vertical axis. (multiply by ~2 to get radius.)"))
|
|
Packit |
bc1512 |
gegl_chant_string (filter, _("Filter"), "auto",
|
|
Packit |
bc1512 |
_("Optional parameter to override the automatic selection of blur filter. "
|
|
Packit |
bc1512 |
"Choices are fir, iir, auto"))
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#else
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#define GEGL_CHANT_TYPE_AREA_FILTER
|
|
Packit |
bc1512 |
#define GEGL_CHANT_C_FILE "gaussian-blur.c"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "gegl-chant.h"
|
|
Packit |
bc1512 |
#include <math.h>
|
|
Packit |
bc1512 |
#include <stdio.h>
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#define RADIUS_SCALE 4
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
iir_young_find_constants (gfloat radius,
|
|
Packit |
bc1512 |
gdouble *B,
|
|
Packit |
bc1512 |
gdouble *b);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gint
|
|
Packit |
bc1512 |
fir_gen_convolve_matrix (gdouble sigma,
|
|
Packit |
bc1512 |
gdouble **cmatrix_p);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
iir_young_find_constants (gfloat sigma,
|
|
Packit |
bc1512 |
gdouble *B,
|
|
Packit |
bc1512 |
gdouble *b)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gdouble q;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (sigma == 0.0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
/* to prevent unexpected ringing at tile boundaries,
|
|
Packit |
bc1512 |
we define an (expensive) copy operation here */
|
|
Packit |
bc1512 |
*B = 1.0;
|
|
Packit |
bc1512 |
b[0] = 1.0;
|
|
Packit |
bc1512 |
b[1] = b[2] = b[3] = 0.0;
|
|
Packit |
bc1512 |
return;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if(sigma >= 2.5)
|
|
Packit |
bc1512 |
q = 0.98711*sigma - 0.96330;
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
q = 3.97156 - 4.14554*sqrt(1-0.26891*sigma);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
b[0] = 1.57825 + (2.44413*q) + (1.4281*q*q) + (0.422205*q*q*q);
|
|
Packit |
bc1512 |
b[1] = (2.44413*q) + (2.85619*q*q) + (1.26661*q*q*q);
|
|
Packit |
bc1512 |
b[2] = -((1.4281*q*q) + (1.26661*q*q*q));
|
|
Packit |
bc1512 |
b[3] = 0.422205*q*q*q;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
*B = 1 - ( (b[1]+b[2]+b[3])/b[0] );
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline void
|
|
Packit |
bc1512 |
iir_young_blur_1D (gfloat * buf,
|
|
Packit |
bc1512 |
gint offset,
|
|
Packit |
bc1512 |
gint delta_offset,
|
|
Packit |
bc1512 |
gdouble B,
|
|
Packit |
bc1512 |
gdouble * b,
|
|
Packit |
bc1512 |
gfloat * w,
|
|
Packit |
bc1512 |
gint w_len)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint wcount, i;
|
|
Packit |
bc1512 |
gdouble tmp;
|
|
Packit |
bc1512 |
gdouble recip = 1.0 / b[0];
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* forward filter */
|
|
Packit |
bc1512 |
wcount = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (wcount < w_len)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
tmp = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=1; i<4; i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (wcount-i >= 0)
|
|
Packit |
bc1512 |
tmp += b[i]*w[wcount-i];
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
tmp *= recip;
|
|
Packit |
bc1512 |
tmp += B*buf[offset];
|
|
Packit |
bc1512 |
w[wcount] = tmp;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
wcount++;
|
|
Packit |
bc1512 |
offset += delta_offset;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* backward filter */
|
|
Packit |
bc1512 |
wcount = w_len - 1;
|
|
Packit |
bc1512 |
offset -= delta_offset;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (wcount >= 0)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
tmp = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=1; i<4; i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (wcount+i < w_len)
|
|
Packit |
bc1512 |
tmp += b[i]*buf[offset+delta_offset*i];
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
tmp *= recip;
|
|
Packit |
bc1512 |
tmp += B*w[wcount];
|
|
Packit |
bc1512 |
buf[offset] = tmp;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
offset -= delta_offset;
|
|
Packit |
bc1512 |
wcount--;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* expects src and dst buf to have the same height and no y-offset */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
iir_young_hor_blur (GeglBuffer *src,
|
|
Packit |
bc1512 |
const GeglRectangle *src_rect,
|
|
Packit |
bc1512 |
GeglBuffer *dst,
|
|
Packit |
bc1512 |
const GeglRectangle *dst_rect,
|
|
Packit |
bc1512 |
gdouble B,
|
|
Packit |
bc1512 |
gdouble *b)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint v;
|
|
Packit |
bc1512 |
gint c;
|
|
Packit |
bc1512 |
gint w_len;
|
|
Packit |
bc1512 |
gfloat *buf;
|
|
Packit |
bc1512 |
gfloat *w;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
buf = g_new0 (gfloat, src_rect->height * src_rect->width * 4);
|
|
Packit |
bc1512 |
w = g_new0 (gfloat, src_rect->width);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_get (src, src_rect, 1.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
w_len = src_rect->width;
|
|
Packit |
bc1512 |
for (v=0; v<src_rect->height; v++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
for (c = 0; c < 4; c++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
iir_young_blur_1D (buf,
|
|
Packit |
bc1512 |
v*src_rect->width*4+c,
|
|
Packit |
bc1512 |
4,
|
|
Packit |
bc1512 |
B,
|
|
Packit |
bc1512 |
b,
|
|
Packit |
bc1512 |
w,
|
|
Packit |
bc1512 |
w_len);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_set (dst, src_rect, 0.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit |
bc1512 |
g_free (buf);
|
|
Packit |
bc1512 |
g_free (w);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* expects src and dst buf to have the same width and no x-offset */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
iir_young_ver_blur (GeglBuffer *src,
|
|
Packit |
bc1512 |
const GeglRectangle *src_rect,
|
|
Packit |
bc1512 |
GeglBuffer *dst,
|
|
Packit |
bc1512 |
const GeglRectangle *dst_rect,
|
|
Packit |
bc1512 |
gdouble B,
|
|
Packit |
bc1512 |
gdouble *b)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint u;
|
|
Packit |
bc1512 |
gint c;
|
|
Packit |
bc1512 |
gint w_len;
|
|
Packit |
bc1512 |
gfloat *buf;
|
|
Packit |
bc1512 |
gfloat *w;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
buf = g_new0 (gfloat, src_rect->height * src_rect->width * 4);
|
|
Packit |
bc1512 |
w = g_new0 (gfloat, src_rect->height);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_get (src, src_rect, 1.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
w_len = src_rect->height;
|
|
Packit |
bc1512 |
for (u=0; u<dst_rect->width; u++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
for (c = 0; c < 4; c++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
iir_young_blur_1D (buf,
|
|
Packit |
bc1512 |
u*4 + c,
|
|
Packit |
bc1512 |
src_rect->width*4,
|
|
Packit |
bc1512 |
B,
|
|
Packit |
bc1512 |
b,
|
|
Packit |
bc1512 |
w,
|
|
Packit |
bc1512 |
w_len);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_set (dst, src_rect, 0,
|
|
Packit |
bc1512 |
babl_format ("RaGaBaA float"), buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit |
bc1512 |
g_free (buf);
|
|
Packit |
bc1512 |
g_free (w);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gint
|
|
Packit |
bc1512 |
fir_calc_convolve_matrix_length (gdouble sigma)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
return sigma ? ceil (sigma)*6.0+1.0 : 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gint
|
|
Packit |
bc1512 |
fir_gen_convolve_matrix (gdouble sigma,
|
|
Packit |
bc1512 |
gdouble **cmatrix_p)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint matrix_length;
|
|
Packit |
bc1512 |
gdouble *cmatrix;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
matrix_length = fir_calc_convolve_matrix_length (sigma);
|
|
Packit |
bc1512 |
cmatrix = g_new (gdouble, matrix_length);
|
|
Packit |
bc1512 |
if (!cmatrix)
|
|
Packit |
bc1512 |
return 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (matrix_length == 1)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cmatrix[0] = 1;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint i,x;
|
|
Packit |
bc1512 |
gdouble sum = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=0; i
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gdouble y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
x = i - (matrix_length/2);
|
|
Packit |
bc1512 |
y = (1.0/(sigma*sqrt(2.0*G_PI))) * exp(-(x*x) / (2.0*sigma*sigma));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cmatrix[i] = y;
|
|
Packit |
bc1512 |
sum += cmatrix[i];
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=matrix_length/2 + 1; i
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cmatrix[i] = cmatrix[matrix_length-i-1];
|
|
Packit |
bc1512 |
sum += cmatrix[i];
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=0; i
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cmatrix[i] /= sum;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
*cmatrix_p = cmatrix;
|
|
Packit |
bc1512 |
return matrix_length;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static inline float
|
|
Packit |
bc1512 |
fir_get_mean_component_1D (gfloat * buf,
|
|
Packit |
bc1512 |
gint offset,
|
|
Packit |
bc1512 |
gint delta_offset,
|
|
Packit |
bc1512 |
gdouble * cmatrix,
|
|
Packit |
bc1512 |
gint matrix_length)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint i;
|
|
Packit |
bc1512 |
gdouble acc=0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for (i=0; i < matrix_length; i++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
acc += buf[offset] * cmatrix[i];
|
|
Packit |
bc1512 |
offset += delta_offset;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return acc;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* expects src and dst buf to have the same height and no y-offset */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
fir_hor_blur (GeglBuffer *src,
|
|
Packit |
bc1512 |
const GeglRectangle *src_rect,
|
|
Packit |
bc1512 |
GeglBuffer *dst,
|
|
Packit |
bc1512 |
const GeglRectangle *dst_rect,
|
|
Packit |
bc1512 |
gdouble *cmatrix,
|
|
Packit |
bc1512 |
gint matrix_length,
|
|
Packit |
bc1512 |
gint xoff) /* offset between src and dst */
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint u,v;
|
|
Packit |
bc1512 |
gint offset;
|
|
Packit |
bc1512 |
gfloat *src_buf;
|
|
Packit |
bc1512 |
gfloat *dst_buf;
|
|
Packit |
bc1512 |
const gint radius = matrix_length/2;
|
|
Packit |
bc1512 |
const gint src_width = src_rect->width;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (xoff >= radius);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
src_buf = g_new0 (gfloat, src_rect->height * src_rect->width * 4);
|
|
Packit |
bc1512 |
dst_buf = g_new0 (gfloat, dst_rect->height * dst_rect->width * 4);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_get (src, src_rect, 1.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
offset = 0;
|
|
Packit |
bc1512 |
for (v=0; v<dst_rect->height; v++)
|
|
Packit |
bc1512 |
for (u=0; u<dst_rect->width; u++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint src_offset = (u-radius+xoff + v*src_width) * 4;
|
|
Packit |
bc1512 |
gint c;
|
|
Packit |
bc1512 |
for (c=0; c<4; c++)
|
|
Packit |
bc1512 |
dst_buf [offset++] = fir_get_mean_component_1D (src_buf,
|
|
Packit |
bc1512 |
src_offset + c,
|
|
Packit |
bc1512 |
4,
|
|
Packit |
bc1512 |
cmatrix,
|
|
Packit |
bc1512 |
matrix_length);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_set (dst, dst_rect, 0.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
dst_buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit |
bc1512 |
g_free (src_buf);
|
|
Packit |
bc1512 |
g_free (dst_buf);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* expects src and dst buf to have the same width and no x-offset */
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
fir_ver_blur (GeglBuffer *src,
|
|
Packit |
bc1512 |
const GeglRectangle *src_rect,
|
|
Packit |
bc1512 |
GeglBuffer *dst,
|
|
Packit |
bc1512 |
const GeglRectangle *dst_rect,
|
|
Packit |
bc1512 |
gdouble *cmatrix,
|
|
Packit |
bc1512 |
gint matrix_length,
|
|
Packit |
bc1512 |
gint yoff) /* offset between src and dst */
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint u,v;
|
|
Packit |
bc1512 |
gint offset;
|
|
Packit |
bc1512 |
gfloat *src_buf;
|
|
Packit |
bc1512 |
gfloat *dst_buf;
|
|
Packit |
bc1512 |
const gint radius = matrix_length/2;
|
|
Packit |
bc1512 |
const gint src_width = src_rect->width;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_assert (yoff >= radius);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
src_buf = g_new0 (gfloat, src_rect->width * src_rect->height * 4);
|
|
Packit |
bc1512 |
dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_get (src, src_rect, 1.0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
offset=0;
|
|
Packit |
bc1512 |
for (v=0; v< dst_rect->height; v++)
|
|
Packit |
bc1512 |
for (u=0; u< dst_rect->width; u++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
gint src_offset = (u + (v-radius+yoff)*src_width) * 4;
|
|
Packit |
bc1512 |
gint c;
|
|
Packit |
bc1512 |
for (c=0; c<4; c++)
|
|
Packit |
bc1512 |
dst_buf [offset++] = fir_get_mean_component_1D (src_buf,
|
|
Packit |
bc1512 |
src_offset + c,
|
|
Packit |
bc1512 |
src_width * 4,
|
|
Packit |
bc1512 |
cmatrix,
|
|
Packit |
bc1512 |
matrix_length);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_buffer_set (dst, dst_rect, 0, babl_format ("RaGaBaA float"),
|
|
Packit |
bc1512 |
dst_buf, GEGL_AUTO_ROWSTRIDE);
|
|
Packit |
bc1512 |
g_free (src_buf);
|
|
Packit |
bc1512 |
g_free (dst_buf);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void prepare (GeglOperation *operation)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
#define max(A,B) ((A) > (B) ? (A) : (B))
|
|
Packit |
bc1512 |
GeglOperationAreaFilter *area = GEGL_OPERATION_AREA_FILTER (operation);
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gfloat fir_radius_x = fir_calc_convolve_matrix_length (o->std_dev_x) / 2;
|
|
Packit |
bc1512 |
gfloat fir_radius_y = fir_calc_convolve_matrix_length (o->std_dev_y) / 2;
|
|
Packit |
bc1512 |
gfloat iir_radius_x = o->std_dev_x * RADIUS_SCALE;
|
|
Packit |
bc1512 |
gfloat iir_radius_y = o->std_dev_y * RADIUS_SCALE;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
/* XXX: these should be calculated exactly considering o->filter, but we just
|
|
Packit |
bc1512 |
* make sure there is enough space */
|
|
Packit |
bc1512 |
area->left = area->right = ceil ( max (fir_radius_x, iir_radius_x));
|
|
Packit |
bc1512 |
area->top = area->bottom = ceil ( max (fir_radius_y, iir_radius_y));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_operation_set_format (operation, "input",
|
|
Packit |
bc1512 |
babl_format ("RaGaBaA float"));
|
|
Packit |
bc1512 |
gegl_operation_set_format (operation, "output",
|
|
Packit |
bc1512 |
babl_format ("RaGaBaA float"));
|
|
Packit |
bc1512 |
#undef max
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#include "opencl/gegl-cl.h"
|
|
Packit |
bc1512 |
#include "buffer/gegl-buffer-cl-iterator.h"
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static const char* kernel_source =
|
|
Packit |
bc1512 |
"float4 fir_get_mean_component_1D_CL(const global float4 *buf, \n"
|
|
Packit |
bc1512 |
" int offset, \n"
|
|
Packit |
bc1512 |
" const int delta_offset, \n"
|
|
Packit |
bc1512 |
" constant float *cmatrix, \n"
|
|
Packit |
bc1512 |
" const int matrix_length) \n"
|
|
Packit |
bc1512 |
"{ \n"
|
|
Packit |
bc1512 |
" float4 acc = 0.0f; \n"
|
|
Packit |
bc1512 |
" int i; \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
" for(i=0; i
|
|
Packit |
bc1512 |
" { \n"
|
|
Packit |
bc1512 |
" acc += buf[offset] * cmatrix[i]; \n"
|
|
Packit |
bc1512 |
" offset += delta_offset; \n"
|
|
Packit |
bc1512 |
" } \n"
|
|
Packit |
bc1512 |
" return acc; \n"
|
|
Packit |
bc1512 |
"} \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
"__kernel void fir_ver_blur_CL(const global float4 *src_buf, \n"
|
|
Packit |
bc1512 |
" const int src_width, \n"
|
|
Packit |
bc1512 |
" global float4 *dst_buf, \n"
|
|
Packit |
bc1512 |
" constant float *cmatrix, \n"
|
|
Packit |
bc1512 |
" const int matrix_length, \n"
|
|
Packit |
bc1512 |
" const int yoff) \n"
|
|
Packit |
bc1512 |
"{ \n"
|
|
Packit |
bc1512 |
" int gidx = get_global_id(0); \n"
|
|
Packit |
bc1512 |
" int gidy = get_global_id(1); \n"
|
|
Packit |
bc1512 |
" int gid = gidx + gidy * get_global_size(0); \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
" int radius = matrix_length / 2; \n"
|
|
Packit |
bc1512 |
" int src_offset = gidx + (gidy - radius + yoff) * src_width; \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
" dst_buf[gid] = fir_get_mean_component_1D_CL( \n"
|
|
Packit |
bc1512 |
" src_buf, src_offset, src_width, cmatrix, matrix_length); \n"
|
|
Packit |
bc1512 |
"} \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
"__kernel void fir_hor_blur_CL(const global float4 *src_buf, \n"
|
|
Packit |
bc1512 |
" const int src_width, \n"
|
|
Packit |
bc1512 |
" global float4 *dst_buf, \n"
|
|
Packit |
bc1512 |
" constant float *cmatrix, \n"
|
|
Packit |
bc1512 |
" const int matrix_length, \n"
|
|
Packit |
bc1512 |
" const int yoff) \n"
|
|
Packit |
bc1512 |
"{ \n"
|
|
Packit |
bc1512 |
" int gidx = get_global_id(0); \n"
|
|
Packit |
bc1512 |
" int gidy = get_global_id(1); \n"
|
|
Packit |
bc1512 |
" int gid = gidx + gidy * get_global_size(0); \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
" int radius = matrix_length / 2; \n"
|
|
Packit |
bc1512 |
" int src_offset = gidy * src_width + (gidx - radius + yoff); \n"
|
|
Packit |
bc1512 |
" \n"
|
|
Packit |
bc1512 |
" dst_buf[gid] = fir_get_mean_component_1D_CL( \n"
|
|
Packit |
bc1512 |
" src_buf, src_offset, 1, cmatrix, matrix_length); \n"
|
|
Packit |
bc1512 |
"} \n";
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gegl_cl_run_data *cl_data = NULL;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static cl_int
|
|
Packit |
bc1512 |
cl_gaussian_blur (cl_mem in_tex,
|
|
Packit |
bc1512 |
cl_mem out_tex,
|
|
Packit |
bc1512 |
cl_mem aux_tex,
|
|
Packit |
bc1512 |
size_t global_worksize,
|
|
Packit |
bc1512 |
const GeglRectangle *roi,
|
|
Packit |
bc1512 |
const GeglRectangle *src_rect,
|
|
Packit |
bc1512 |
const GeglRectangle *aux_rect,
|
|
Packit |
bc1512 |
gfloat *dmatrix_x,
|
|
Packit |
bc1512 |
gint matrix_length_x,
|
|
Packit |
bc1512 |
gint xoff,
|
|
Packit |
bc1512 |
gfloat *dmatrix_y,
|
|
Packit |
bc1512 |
gint matrix_length_y,
|
|
Packit |
bc1512 |
gint yoff)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cl_int cl_err = 0;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
size_t global_ws[2];
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_mem cl_matrix_x, cl_matrix_y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (!cl_data)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const char *kernel_name[] = {"fir_ver_blur_CL", "fir_hor_blur_CL", NULL};
|
|
Packit |
bc1512 |
cl_data = gegl_cl_compile_and_build (kernel_source, kernel_name);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
if (!cl_data) return 1;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_matrix_x = gegl_clCreateBuffer(gegl_cl_get_context(),
|
|
Packit |
bc1512 |
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
|
|
Packit |
bc1512 |
matrix_length_x * sizeof(cl_float), NULL, &cl_err);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err = gegl_clEnqueueWriteBuffer(gegl_cl_get_command_queue(), cl_matrix_x,
|
|
Packit |
bc1512 |
CL_TRUE, 0, matrix_length_x * sizeof(cl_float), dmatrix_x,
|
|
Packit |
bc1512 |
0, NULL, NULL);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_matrix_y = gegl_clCreateBuffer(gegl_cl_get_context(),
|
|
Packit |
bc1512 |
CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
|
|
Packit |
bc1512 |
matrix_length_y * sizeof(cl_float), NULL, &cl_err);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err = gegl_clEnqueueWriteBuffer(gegl_cl_get_command_queue(), cl_matrix_y,
|
|
Packit |
bc1512 |
CL_TRUE, 0, matrix_length_y * sizeof(cl_float), dmatrix_y,
|
|
Packit |
bc1512 |
0, NULL, NULL);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
global_ws[0] = aux_rect->width;
|
|
Packit |
bc1512 |
global_ws[1] = aux_rect->height;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 0, sizeof(cl_mem), (void*)&in_tex);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 1, sizeof(cl_int), (void*)&src_rect->width);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 2, sizeof(cl_mem), (void*)&aux_tex);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 3, sizeof(cl_mem), (void*)&cl_matrix_x);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 4, sizeof(cl_int), (void*)&matrix_length_x);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[1], 5, sizeof(cl_int), (void*)&xoff);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
|
|
Packit |
bc1512 |
cl_data->kernel[1], 2,
|
|
Packit |
bc1512 |
NULL, global_ws, NULL,
|
|
Packit |
bc1512 |
0, NULL, NULL);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
global_ws[0] = roi->width;
|
|
Packit |
bc1512 |
global_ws[1] = roi->height;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem), (void*)&aux_tex);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_int), (void*)&aux_rect->width);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_mem), (void*)&out_tex);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(cl_mem), (void*)&cl_matrix_y);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 4, sizeof(cl_int), (void*)&matrix_length_y);
|
|
Packit |
bc1512 |
cl_err |= gegl_clSetKernelArg(cl_data->kernel[0], 5, sizeof(cl_int), (void*)&yoff);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
|
|
Packit |
bc1512 |
cl_data->kernel[0], 2,
|
|
Packit |
bc1512 |
NULL, global_ws, NULL,
|
|
Packit |
bc1512 |
0, NULL, NULL);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS) return cl_err;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_clFinish(gegl_cl_get_command_queue ());
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_clReleaseMemObject(cl_matrix_x);
|
|
Packit |
bc1512 |
gegl_clReleaseMemObject(cl_matrix_y);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
return CL_SUCCESS;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gboolean
|
|
Packit |
bc1512 |
cl_process (GeglOperation *operation,
|
|
Packit |
bc1512 |
GeglBuffer *input,
|
|
Packit |
bc1512 |
GeglBuffer *output,
|
|
Packit |
bc1512 |
const GeglRectangle *result)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
const Babl *in_format = gegl_operation_get_format (operation, "input");
|
|
Packit |
bc1512 |
const Babl *out_format = gegl_operation_get_format (operation, "output");
|
|
Packit |
bc1512 |
gint err;
|
|
Packit |
bc1512 |
gint j;
|
|
Packit |
bc1512 |
cl_int cl_err;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gdouble *cmatrix_x, *cmatrix_y;
|
|
Packit |
bc1512 |
gint cmatrix_len_x, cmatrix_len_y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gfloat *fmatrix_x, *fmatrix_y;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
cmatrix_len_x = fir_gen_convolve_matrix (o->std_dev_x, &cmatrix_x);
|
|
Packit |
bc1512 |
cmatrix_len_y = fir_gen_convolve_matrix (o->std_dev_y, &cmatrix_y);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
fmatrix_x = g_new (gfloat, cmatrix_len_x);
|
|
Packit |
bc1512 |
fmatrix_y = g_new (gfloat, cmatrix_len_y);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for(j=0; j
|
|
Packit |
bc1512 |
fmatrix_x[j] = (gfloat) cmatrix_x[j];
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
for(j=0; j
|
|
Packit |
bc1512 |
fmatrix_y[j] = (gfloat) cmatrix_y[j];
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, result, out_format, GEGL_CL_BUFFER_WRITE, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
gint read = gegl_buffer_cl_iterator_add_2 (i, input, result, in_format, GEGL_CL_BUFFER_READ,
|
|
Packit |
bc1512 |
op_area->left, op_area->right, op_area->top, op_area->bottom, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
gint aux = gegl_buffer_cl_iterator_add_2 (i, NULL, result, in_format, GEGL_CL_BUFFER_AUX,
|
|
Packit |
bc1512 |
0, 0, op_area->top, op_area->bottom, GEGL_ABYSS_NONE);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
while (gegl_buffer_cl_iterator_next (i, &err))
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
if (err) return FALSE;
|
|
Packit |
bc1512 |
for (j=0; j < i->n; j++)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cl_err = cl_gaussian_blur(i->tex[read][j],
|
|
Packit |
bc1512 |
i->tex[0][j],
|
|
Packit |
bc1512 |
i->tex[aux][j],
|
|
Packit |
bc1512 |
i->size[0][j],
|
|
Packit |
bc1512 |
&i->roi[0][j],
|
|
Packit |
bc1512 |
&i->roi[read][j],
|
|
Packit |
bc1512 |
&i->roi[aux][j],
|
|
Packit |
bc1512 |
fmatrix_x,
|
|
Packit |
bc1512 |
cmatrix_len_x,
|
|
Packit |
bc1512 |
op_area->left,
|
|
Packit |
bc1512 |
fmatrix_y,
|
|
Packit |
bc1512 |
cmatrix_len_y,
|
|
Packit |
bc1512 |
op_area->top);
|
|
Packit |
bc1512 |
if (cl_err != CL_SUCCESS)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
g_warning("[OpenCL] Error in gegl:gaussian-blur: %s", gegl_cl_errstring(cl_err));
|
|
Packit |
bc1512 |
return FALSE;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (fmatrix_x);
|
|
Packit |
bc1512 |
g_free (fmatrix_y);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_free (cmatrix_x);
|
|
Packit |
bc1512 |
g_free (cmatrix_y);
|
|
Packit |
bc1512 |
return TRUE;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static gboolean
|
|
Packit |
bc1512 |
process (GeglOperation *operation,
|
|
Packit |
bc1512 |
GeglBuffer *input,
|
|
Packit |
bc1512 |
GeglBuffer *output,
|
|
Packit |
bc1512 |
const GeglRectangle *result,
|
|
Packit |
bc1512 |
gint level)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglRectangle rect;
|
|
Packit |
bc1512 |
GeglBuffer *temp;
|
|
Packit |
bc1512 |
GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation);
|
|
Packit |
bc1512 |
GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
GeglRectangle temp_extend;
|
|
Packit |
bc1512 |
gdouble B, b[4];
|
|
Packit |
bc1512 |
gdouble *cmatrix;
|
|
Packit |
bc1512 |
gint cmatrix_len;
|
|
Packit |
bc1512 |
gboolean force_iir;
|
|
Packit |
bc1512 |
gboolean force_fir;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
rect.x = result->x - op_area->left;
|
|
Packit |
bc1512 |
rect.width = result->width + op_area->left + op_area->right;
|
|
Packit |
bc1512 |
rect.y = result->y - op_area->top;
|
|
Packit |
bc1512 |
rect.height = result->height + op_area->top + op_area->bottom;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
force_iir = o->filter && !strcmp (o->filter, "iir");
|
|
Packit |
bc1512 |
force_fir = o->filter && !strcmp (o->filter, "fir");
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if (gegl_cl_is_accelerated () && !force_iir)
|
|
Packit |
bc1512 |
if (cl_process(operation, input, output, result))
|
|
Packit |
bc1512 |
return TRUE;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
temp_extend = rect;
|
|
Packit |
bc1512 |
temp_extend.x = result->x;
|
|
Packit |
bc1512 |
temp_extend.width = result->width;
|
|
Packit |
bc1512 |
temp = gegl_buffer_new (&temp_extend, babl_format ("RaGaBaA float"));
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if ((force_iir || o->std_dev_x > 1.0) && !force_fir)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
iir_young_find_constants (o->std_dev_x, &B, b);
|
|
Packit |
bc1512 |
iir_young_hor_blur (input, &rect, temp, &temp_extend, B, b);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cmatrix_len = fir_gen_convolve_matrix (o->std_dev_x, &cmatrix);
|
|
Packit |
bc1512 |
fir_hor_blur (input, &rect, temp, &temp_extend,
|
|
Packit |
bc1512 |
cmatrix, cmatrix_len, op_area->left);
|
|
Packit |
bc1512 |
g_free (cmatrix);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
if ((force_iir || o->std_dev_y > 1.0) && !force_fir)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
iir_young_find_constants (o->std_dev_y, &B, b);
|
|
Packit |
bc1512 |
iir_young_ver_blur (temp, &temp_extend, output, result, B, b);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
else
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
cmatrix_len = fir_gen_convolve_matrix (o->std_dev_y, &cmatrix);
|
|
Packit |
bc1512 |
fir_ver_blur (temp, &temp_extend, output, result, cmatrix, cmatrix_len,
|
|
Packit |
bc1512 |
op_area->top);
|
|
Packit |
bc1512 |
g_free (cmatrix);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
g_object_unref (temp);
|
|
Packit |
bc1512 |
return TRUE;
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
static void
|
|
Packit |
bc1512 |
gegl_chant_class_init (GeglChantClass *klass)
|
|
Packit |
bc1512 |
{
|
|
Packit |
bc1512 |
GeglOperationClass *operation_class;
|
|
Packit |
bc1512 |
GeglOperationFilterClass *filter_class;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
operation_class = GEGL_OPERATION_CLASS (klass);
|
|
Packit |
bc1512 |
filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
filter_class->process = process;
|
|
Packit |
bc1512 |
operation_class->prepare = prepare;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
operation_class->opencl_support = TRUE;
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
gegl_operation_class_set_keys (operation_class,
|
|
Packit |
bc1512 |
"name", "gegl:gaussian-blur",
|
|
Packit |
bc1512 |
"categories", "blur",
|
|
Packit |
bc1512 |
"description",
|
|
Packit |
bc1512 |
_("Performs an averaging of neighboring pixels with the "
|
|
Packit |
bc1512 |
"normal distribution as weighting"),
|
|
Packit |
bc1512 |
NULL);
|
|
Packit |
bc1512 |
}
|
|
Packit |
bc1512 |
|
|
Packit |
bc1512 |
#endif
|