static void snn_percentile (GeglBuffer *src, GeglBuffer *dst, gdouble radius, gdouble percentile, gint pairs) { gint x, y; gint offset; gfloat *src_buf; gfloat *dst_buf; RankList list = {0}; src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4); dst_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (dst) * 4); gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); offset = 0; percentile/= 100.0; for (y=0; y<gegl_buffer_get_height (dst); y++) for (x=0; x<gegl_buffer_get_width (dst); x++) { gint u,v; gfloat *center_pix = src_buf + offset * 4; list_clear (&list); /* iterate through the upper left quater of pixels */ for (v=-radius;v<=0;v++) for (u=-radius;u<= (pairs==1?radius:0);u++) { gfloat *selected_pix = center_pix; gfloat best_diff = 1000.0; gint i; /* skip computations for the center pixel */ if (u != 0 && v != 0) { /* compute the coordinates of the symmetric pairs for * this locaiton in the quadrant */ gint xs[4] = {x+u, x-u, x-u, x+u}; gint ys[4] = {y+v, y-v, y+v, y-v}; /* check which member of the symmetric quadruple to use */ for (i=0;i<pairs*2;i++) { if (xs[i] >= 0 && xs[i] < gegl_buffer_get_width (src) && ys[i] >= 0 && ys[i] < gegl_buffer_get_height (src)) { gfloat *tpix = src_buf + (xs[i]+ys[i]*gegl_buffer_get_width (src))*4; gfloat diff = colordiff (tpix, center_pix); if (diff < best_diff) { best_diff = diff; selected_pix = tpix; } } } } list_add (&list, rgb2luminance(selected_pix), selected_pix); if (u==0 && v==0) break; /* to avoid doubly processing when using only 1 pair */ } { gfloat *result = list_percentile (&list, percentile); for (u=0; u<4; u++) dst_buf[offset*4+u] = result[u]; } offset++; } gegl_buffer_set (dst, NULL, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }
static void snn_mean (GeglBuffer *src, GeglBuffer *dst, const GeglRectangle *dst_rect, gdouble dradius, gint pairs) { gint x,y; gint offset; gfloat *src_buf; gfloat *dst_buf; gint radius = dradius; gint src_width = gegl_buffer_get_width (src); gint src_height = gegl_buffer_get_height (src); src_buf = g_new0 (gfloat, gegl_buffer_get_pixel_count (src) * 4); dst_buf = g_new0 (gfloat, dst_rect->width * dst_rect->height * 4); gegl_buffer_get (src, NULL, 1.0, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); offset = 0; for (y=0; y<dst_rect->height; y++) { gfloat *center_pix; center_pix = src_buf + ((radius) + (y+radius)* src_width)*4; for (x=0; x<dst_rect->width; x++) { gint u,v; gfloat accumulated[4]={0,}; gint count=0; /* iterate through the upper left quater of pixels */ for (v=-radius;v<=0;v++) for (u=-radius;u<= (pairs==1?radius:0);u++) { gfloat *selected_pix = center_pix; gfloat best_diff = 1000.0; gint i; /* skip computations for the center pixel */ if (u != 0 && v != 0) { /* compute the coordinates of the symmetric pairs for * this locaiton in the quadrant */ gint xs[4], ys[4]; xs[0] = x+u+radius; xs[1] = x-u+radius; xs[2] = x-u+radius; xs[3] = x+u+radius; ys[0] = y+v+radius; ys[1] = y-v+radius; ys[2] = y+v+radius; ys[3] = y-v+radius; /* check which member of the symmetric quadruple to use */ for (i=0;i<pairs*2;i++) { if (xs[i] >= 0 && xs[i] < src_width && ys[i] >= 0 && ys[i] < src_height) { gfloat *tpix = src_buf + (xs[i]+ys[i]* src_width)*4; gfloat diff = colordiff (tpix, center_pix); if (diff < best_diff) { best_diff = diff; selected_pix = tpix; } } } } /* accumulate the components of the best sample from * the symmetric quadruple */ for (i=0;i<4;i++) { accumulated[i] += selected_pix[i]; } count++; if (u==0 && v==0) break; /* to avoid doubly processing when using only 1 pair */ } for (u=0; u<4; u++) dst_buf[offset*4+u] = accumulated[u]/count; offset++; center_pix += 4; } } gegl_buffer_set (dst, dst_rect, 0, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }