static void despeckle_median (guchar *src, guchar *dst, gint width, gint height, gint bpp, gint radius, gboolean preview) { guint progress; guint max_progress; gint x, y; gint input_radius = radius; gint pos; gint ymin; gint ymax; gint xmin; gint xmax; memset (&histogram, 0, sizeof(histogram)); progress = 0; max_progress = width * height; if (! preview) gimp_progress_init(_("Despeckle")); for (y = 0; y < height; y++) { x = 0; ymin = MAX (0, y - radius); ymax = MIN (height - 1, y + radius); xmin = MAX (0, x - radius); xmax = MIN (width - 1, x + radius); hist0 = 0; histrest = 0; hist255 = 0; histogram_clean (&histogram); histogram.xmin = xmin; histogram.ymin = ymin; histogram.xmax = xmax; histogram.ymax = ymax; add_vals (&histogram, src, width, bpp, histogram.xmin, histogram.ymin, histogram.xmax, histogram.ymax); for (x = 0; x < width; x++) { const guchar *pixel; ymin = MAX (0, y - radius); /* update ymin, ymax when radius changed (FILTER_ADAPTIVE) */ ymax = MIN (height - 1, y + radius); xmin = MAX (0, x - radius); xmax = MIN (width - 1, x + radius); update_histogram (&histogram, src, width, bpp, xmin, ymin, xmax, ymax); pos = (x + (y * width)) * bpp; pixel = histogram_get_median (&histogram, src + pos); if (filter_type & FILTER_RECURSIVE) { del_val (&histogram, src, width, bpp, x, y); pixel_copy (src + pos, pixel, bpp); add_val (&histogram, src, width, bpp, x, y); } pixel_copy (dst + pos, pixel, bpp); /* * Check the histogram and adjust the diameter accordingly... */ if (filter_type & FILTER_ADAPTIVE) { if (hist0 >= radius || hist255 >= radius) { if (radius < input_radius) radius++; } else if (radius > 1) { radius--; } } } progress += width; if (! preview && y % 32 == 0) gimp_progress_update ((gdouble) progress / (gdouble) max_progress); } if (! preview) gimp_progress_update (1.0); }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gdouble percentile = o->percentile / 100.0; gdouble alpha_percentile = o->alpha_percentile / 100.0; const gint *neighborhood_outline = o->user_data; const Babl *format = gegl_operation_get_format (operation, "input"); gint n_components = babl_format_get_n_components (format); gboolean has_alpha = babl_format_has_alpha (format); G_STATIC_ASSERT (sizeof (gint32) == sizeof (gfloat)); gint32 *src_buf; gfloat *dst_buf; GeglRectangle src_rect; gint src_stride; gint dst_stride; gint n_pixels; Histogram *hist; const gint32 *src; gfloat *dst; gint dst_x, dst_y; Direction dir; gint i; gint c; src_rect = gegl_operation_get_required_for_output (operation, "input", roi); src_stride = src_rect.width * n_components; dst_stride = roi->width * n_components; n_pixels = roi->width * roi->height; dst_buf = g_new0 (gfloat, n_pixels * n_components); src_buf = g_new0 (gint32, src_rect.width * src_rect.height * n_components); gegl_buffer_get (input, &src_rect, 1.0, format, src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); convert_values_to_bins (src_buf, n_components, has_alpha, src_rect.width * src_rect.height); hist = g_slice_new0 (Histogram); src = src_buf + o->radius * (src_rect.width + 1) * n_components; dst = dst_buf; /* compute the first window */ for (i = -o->radius; i <= o->radius; i++) { histogram_modify_vals (hist, src, n_components, src_stride, has_alpha, i, -neighborhood_outline[abs (i)], i, +neighborhood_outline[abs (i)], +1); hist->size += 2 * neighborhood_outline[abs (i)] + 1; } for (c = 0; c < 3; c++) dst[c] = histogram_get_median (hist, c, percentile); if (has_alpha) dst[3] = histogram_get_median (hist, 3, alpha_percentile); dst_x = 0; dst_y = 0; n_pixels--; dir = LEFT_TO_RIGHT; while (n_pixels--) { /* move the src coords based on current direction and positions */ if (dir == LEFT_TO_RIGHT) { if (dst_x != roi->width - 1) { dst_x++; src += n_components; dst += n_components; } else { dst_y++; src += src_stride; dst += dst_stride; dir = TOP_TO_BOTTOM; } } else if (dir == TOP_TO_BOTTOM) { if (dst_x == 0) { dst_x++; src += n_components; dst += n_components; dir = LEFT_TO_RIGHT; } else { dst_x--; src -= n_components; dst -= n_components; dir = RIGHT_TO_LEFT; } } else if (dir == RIGHT_TO_LEFT) { if (dst_x != 0) { dst_x--; src -= n_components; dst -= n_components; } else { dst_y++; src += src_stride; dst += dst_stride; dir = TOP_TO_BOTTOM; } } histogram_update (hist, src, n_components, src_stride, has_alpha, o->neighborhood, o->radius, neighborhood_outline, dir); for (c = 0; c < 3; c++) dst[c] = histogram_get_median (hist, c, percentile); if (has_alpha) dst[3] = histogram_get_median (hist, 3, alpha_percentile); } gegl_buffer_set (output, roi, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_slice_free (Histogram, hist); g_free (dst_buf); g_free (src_buf); return TRUE; }
static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *roi, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); const Babl *format = gegl_operation_get_format (operation, "input"); gint n_components = babl_format_get_n_components (format); gboolean has_alpha = babl_format_has_alpha (format); gfloat *src_buf; gfloat *dst_buf; gint n_pixels; GeglRectangle src_rect; Histogram *hist; Direction dir; gint src_x, src_y; gint dst_x, dst_y; gint dst_idx, src_idx; gint xmin, ymin, xmax, ymax; src_rect = gegl_operation_get_required_for_output (operation, "input", roi); n_pixels = roi->width * roi->height; dst_buf = g_new0 (gfloat, n_pixels * n_components); src_buf = g_new0 (gfloat, src_rect.width * src_rect.height * n_components); gegl_buffer_get (input, &src_rect, 1.0, format, src_buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP); hist = g_slice_new0 (Histogram); dst_x = 0; dst_y = 0; src_x = o->radius; src_y = o->radius; /* compute the first window */ hist->xmin = src_x - o->radius; hist->ymin = src_y - o->radius; hist->xmax = src_x + o->radius; hist->ymax = src_y + o->radius; histogram_add_vals (hist, src_buf, &src_rect, n_components, hist->xmin, hist->ymin, hist->xmax, hist->ymax); dst_idx = (dst_x + dst_y * roi->width) * n_components; dst_buf[dst_idx] = histogram_get_median (hist, 0); dst_buf[dst_idx + 1] = histogram_get_median (hist, 1); dst_buf[dst_idx + 2] = histogram_get_median (hist, 2); if (has_alpha) { src_idx = (src_x + src_y * src_rect.width) * n_components; dst_buf[dst_idx + 3] = src_buf[src_idx + 3]; } n_pixels--; dir = LEFT_TO_RIGHT; while (n_pixels--) { /* move the src coords based on current direction and positions */ if (dir == LEFT_TO_RIGHT) { if (dst_x != roi->width - 1) { src_x++; dst_x++; } else { src_y++; dst_y++; dir = TOP_TO_BOTTOM; } } else if (dir == TOP_TO_BOTTOM) { if (dst_x == 0) { src_x++; dst_x++; dir = LEFT_TO_RIGHT; } else { src_x--; dst_x--; dir = RIGHT_TO_LEFT; } } else if (dir == RIGHT_TO_LEFT) { if (dst_x != 0) { src_x--; dst_x--; } else { src_y++; dst_y++; dir = TOP_TO_BOTTOM; } } xmin = src_x - o->radius; ymin = src_y - o->radius; xmax = src_x + o->radius; ymax = src_y + o->radius; histogram_update (hist, src_buf, &src_rect, n_components, xmin, ymin, xmax, ymax, dir); dst_idx = (dst_x + dst_y * roi->width) * n_components; dst_buf[dst_idx] = histogram_get_median (hist, 0); dst_buf[dst_idx + 1] = histogram_get_median (hist, 1); dst_buf[dst_idx + 2] = histogram_get_median (hist, 2); if (has_alpha) { src_idx = (src_x + src_y * src_rect.width) * n_components; dst_buf[dst_idx + 3] = src_buf[src_idx + 3]; } } gegl_buffer_set (output, roi, 0, format, dst_buf, GEGL_AUTO_ROWSTRIDE); g_free (src_buf); g_free (dst_buf); g_slice_free (Histogram, hist); return TRUE; }