GeglBuffer * gimp_image_contiguous_region_by_color (GimpImage *image, GimpDrawable *drawable, gboolean sample_merged, gboolean antialias, gfloat threshold, gboolean select_transparent, GimpSelectCriterion select_criterion, const GimpRGB *color) { /* Scan over the image's active layer, finding pixels within the * specified threshold from the given R, G, & B values. If * antialiasing is on, use the same antialiasing scheme as in * fuzzy_select. Modify the image's mask to reflect the * additional selection */ GeglBufferIterator *iter; GimpPickable *pickable; GeglBuffer *src_buffer; GeglBuffer *mask_buffer; const Babl *format; gint n_components; gboolean has_alpha; gfloat start_col[MAX_CHANNELS]; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL); g_return_val_if_fail (color != NULL, NULL); if (sample_merged) pickable = GIMP_PICKABLE (image); else pickable = GIMP_PICKABLE (drawable); gimp_pickable_flush (pickable); src_buffer = gimp_pickable_get_buffer (pickable); format = choose_format (src_buffer, select_criterion, &n_components, &has_alpha); gimp_rgba_get_pixel (color, format, start_col); if (has_alpha) { if (select_transparent) { /* don't select transparancy if "color" isn't fully transparent */ if (start_col[n_components - 1] > 0.0) select_transparent = FALSE; } } else { select_transparent = FALSE; } mask_buffer = gegl_buffer_new (gegl_buffer_get_extent (src_buffer), babl_format ("Y float")); iter = gegl_buffer_iterator_new (src_buffer, NULL, 0, format, GEGL_BUFFER_READ, GEGL_ABYSS_NONE); gegl_buffer_iterator_add (iter, mask_buffer, NULL, 0, babl_format ("Y float"), GEGL_BUFFER_WRITE, GEGL_ABYSS_NONE); while (gegl_buffer_iterator_next (iter)) { const gfloat *src = iter->data[0]; gfloat *dest = iter->data[1]; gint count = iter->length; while (count--) { /* Find how closely the colors match */ *dest = pixel_difference (start_col, src, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); src += n_components; dest += 1; } } return mask_buffer; }
static gboolean find_contiguous_segment (const gfloat *col, GeglBuffer *src_buffer, GeglBuffer *mask_buffer, const Babl *format, gint n_components, gboolean has_alpha, gint width, gboolean select_transparent, GimpSelectCriterion select_criterion, gboolean antialias, gfloat threshold, gint initial_x, gint initial_y, gint *start, gint *end) { gfloat s[MAX_CHANNELS]; gfloat mask_row[width]; gfloat diff; gegl_buffer_sample (src_buffer, initial_x, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); /* check the starting pixel */ if (! diff) return FALSE; mask_row[initial_x] = diff; *start = initial_x - 1; while (*start >= 0 && diff) { gegl_buffer_sample (src_buffer, *start, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); mask_row[*start] = diff; if (diff) (*start)--; } diff = 1; *end = initial_x + 1; while (*end < width && diff) { gegl_buffer_sample (src_buffer, *end, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); mask_row[*end] = diff; if (diff) (*end)++; } gegl_buffer_set (mask_buffer, GEGL_RECTANGLE (*start, initial_y, *end - *start, 1), 0, babl_format ("Y float"), &mask_row[*start], GEGL_AUTO_ROWSTRIDE); return TRUE; }
static gboolean find_contiguous_segment (const gfloat *col, GeglBuffer *src_buffer, GeglBuffer *mask_buffer, const Babl *format, gint n_components, gboolean has_alpha, gint width, gboolean select_transparent, GimpSelectCriterion select_criterion, gboolean antialias, gfloat threshold, gint initial_x, gint initial_y, gint *start, gint *end, gfloat *row) { gfloat *s; gfloat mask_row[width]; gfloat diff; #ifdef FETCH_ROW gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, initial_y, width, 1), 1.0, format, row, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); s = row + initial_x * n_components; #else s = g_alloca (n_components * sizeof (gfloat)); gegl_buffer_sample (src_buffer, initial_x, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); #endif diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); /* check the starting pixel */ if (! diff) return FALSE; mask_row[initial_x] = diff; *start = initial_x - 1; #ifdef FETCH_ROW s = row + *start * n_components; #endif while (*start >= 0 && diff) { #ifndef FETCH_ROW gegl_buffer_sample (src_buffer, *start, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); #endif diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); mask_row[*start] = diff; if (diff) { (*start)--; #ifdef FETCH_ROW s -= n_components; #endif } } diff = 1; *end = initial_x + 1; #ifdef FETCH_ROW s = row + *end * n_components; #endif while (*end < width && diff) { #ifndef FETCH_ROW gegl_buffer_sample (src_buffer, *end, initial_y, NULL, s, format, GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE); #endif diff = pixel_difference (col, s, antialias, threshold, n_components, has_alpha, select_transparent, select_criterion); mask_row[*end] = diff; if (diff) { (*end)++; #ifdef FETCH_ROW s += n_components; #endif } } gegl_buffer_set (mask_buffer, GEGL_RECTANGLE (*start, initial_y, *end - *start, 1), 0, babl_format ("Y float"), &mask_row[*start], GEGL_AUTO_ROWSTRIDE); return TRUE; }