static void median (GeglBuffer *src, GeglBuffer *dst, gint radius, gdouble rank) { RankList list = {0}; gint x,y; gint offset; gfloat *src_buf; gfloat *dst_buf; 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; for (y=0; y<gegl_buffer_get_height (dst); y++) for (x=0; x<gegl_buffer_get_width (dst); x++) { gint u,v; gfloat *median_pix; list_clear (&list); for (v=y-radius;v<=y+radius;v++) for (u=x-radius;u<=x+radius;u++) { gint ru, rv; ru = (x-u)*(x-u); rv = (y-v)*(y-v); if (u >= 0 && u < gegl_buffer_get_width (dst) && v >= 0 && v < gegl_buffer_get_height (dst) && (ru+rv) < radius* radius ) { gfloat *src_pix = src_buf + (u+(v * gegl_buffer_get_width (src))) * 4; gfloat luma = (src_pix[0] * 0.212671 + src_pix[1] * 0.715160 + src_pix[2] * 0.072169); list_add (&list, luma, src_pix); } } median_pix = list_percentile (&list, rank); for (u=0; u<4;u++) dst_buf[offset*4+u] = median_pix[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_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, 1.0, NULL, babl_format ("RGBA float"), src_buf, GEGL_AUTO_ROWSTRIDE); 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, babl_format ("RGBA float"), dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); }