[gimp] app: various performance improvements to fuzzy-select/bucket-fill
- From: N/A <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: various performance improvements to fuzzy-select/bucket-fill
- Date: Thu, 15 Sep 2016 15:35:50 +0000 (UTC)
commit 7e6d67ac4bd6f2d582d31259626e0c59119a7af1
Author: Ell <ell_se yahoo com>
Date: Thu Sep 15 14:46:59 2016 +0000
app: various performance improvements to fuzzy-select/bucket-fill
thru gimp_pickable_contiguous_region_by_seed()
app/core/gimppickable-contiguous-region.c | 83 ++++++++++++++++-------------
1 files changed, 45 insertions(+), 38 deletions(-)
---
diff --git a/app/core/gimppickable-contiguous-region.c b/app/core/gimppickable-contiguous-region.c
index 663ba63..b1c5dca 100644
--- a/app/core/gimppickable-contiguous-region.c
+++ b/app/core/gimppickable-contiguous-region.c
@@ -53,6 +53,7 @@ static gboolean find_contiguous_segment (const gfloat *col,
GeglBuffer *src_buffer,
GeglBuffer *mask_buffer,
const Babl *src_format,
+ const Babl *mask_format,
gint n_components,
gboolean has_alpha,
gint width,
@@ -337,16 +338,8 @@ pixel_difference (const gfloat *col1,
break;
case GIMP_SELECT_CRITERION_H:
- {
- /* wrap around candidates for the actual distance */
- gfloat dist1 = fabs (col1[0] - col2[0]);
- gfloat dist2 = fabs (col1[0] - 1.0 - col2[0]);
- gfloat dist3 = fabs (col1[0] - col2[0] + 1.0);
-
- max = MIN (dist1, dist2);
- if (max > dist3)
- max = dist3;
- }
+ max = fabs (col1[0] - col2[0]);
+ max = MIN (max, 1.0 - max);
break;
case GIMP_SELECT_CRITERION_S:
@@ -385,7 +378,8 @@ static gboolean
find_contiguous_segment (const gfloat *col,
GeglBuffer *src_buffer,
GeglBuffer *mask_buffer,
- const Babl *format,
+ const Babl *src_format,
+ const Babl *mask_format,
gint n_components,
gboolean has_alpha,
gint width,
@@ -405,13 +399,13 @@ find_contiguous_segment (const gfloat *col,
#ifdef FETCH_ROW
gegl_buffer_get (src_buffer, GEGL_RECTANGLE (0, initial_y, width, 1), 1.0,
- format,
+ src_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_buffer_sample (src_buffer, initial_x, initial_y, NULL, s, src_format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
#endif
@@ -430,59 +424,56 @@ find_contiguous_segment (const gfloat *col,
s = row + *start * n_components;
#endif
- while (*start >= 0 && diff)
+ while (*start >= 0)
{
#ifndef FETCH_ROW
- gegl_buffer_sample (src_buffer, *start, initial_y, NULL, s, format,
+ gegl_buffer_sample (src_buffer, *start, initial_y, NULL, s, src_format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
#endif
diff = pixel_difference (col, s, antialias, threshold,
n_components, has_alpha, select_transparent,
select_criterion);
+ if (diff == 0.0)
+ break;
mask_row[*start] = diff;
- if (diff)
- {
- (*start)--;
+ (*start)--;
#ifdef FETCH_ROW
- s -= n_components;
+ s -= n_components;
#endif
- }
}
- diff = 1;
*end = initial_x + 1;
#ifdef FETCH_ROW
s = row + *end * n_components;
#endif
- while (*end < width && diff)
+ while (*end < width)
{
#ifndef FETCH_ROW
- gegl_buffer_sample (src_buffer, *end, initial_y, NULL, s, format,
+ gegl_buffer_sample (src_buffer, *end, initial_y, NULL, s, src_format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
#endif
diff = pixel_difference (col, s, antialias, threshold,
n_components, has_alpha, select_transparent,
select_criterion);
+ if (diff == 0.0)
+ break;
mask_row[*end] = diff;
- if (diff)
- {
- (*end)++;
+ (*end)++;
#ifdef FETCH_ROW
- s += n_components;
+ 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_buffer_set (mask_buffer, GEGL_RECTANGLE (*start + 1, initial_y,
+ *end - *start - 1, 1),
+ 0, mask_format, &mask_row[*start + 1],
GEGL_AUTO_ROWSTRIDE);
return TRUE;
@@ -503,10 +494,11 @@ find_contiguous_region (GeglBuffer *src_buffer,
gint y,
const gfloat *col)
{
- gint start, end;
- gint new_start, new_end;
- GQueue *coord_stack;
- gfloat *row = NULL;
+ const Babl *mask_format = babl_format ("Y float");
+ gint start, end;
+ gint new_start, new_end;
+ GQueue *coord_stack;
+ gfloat *row = NULL;
#ifdef FETCH_ROW
row = g_new (gfloat, gegl_buffer_get_width (src_buffer) * n_components);
@@ -534,13 +526,20 @@ find_contiguous_region (GeglBuffer *src_buffer,
gfloat val;
gegl_buffer_sample (mask_buffer, x, y, NULL, &val,
- babl_format ("Y float"),
+ mask_format,
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
if (val != 0.0)
- continue;
+ {
+ /* If the current pixel is selected, then we've already visited
+ * the next pixel. (Note that we assume that the maximal image
+ * width is sufficiently low that `x` won't overflow.)
+ */
+ x++;
+ continue;
+ }
if (! find_contiguous_segment (col, src_buffer, mask_buffer,
- format,
+ format, mask_format,
n_components,
has_alpha,
gegl_buffer_get_width (src_buffer),
@@ -550,6 +549,14 @@ find_contiguous_region (GeglBuffer *src_buffer,
row))
continue;
+ /* We can skip directly to `new_end + 1` on the next iteration, since
+ * we've just selected all pixels in the range `[x, new_end)`, and
+ * the pixel at `new_end` is above threshold. (Note that we assume
+ * that the maximal image width is sufficiently low that `x` won't
+ * overflow.)
+ */
+ x = new_end;
+
if (diagonal_neighbors)
{
if (new_start >= 0)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]