app: add "line-art-max-grow" property to the bucket fill options.

When flooding the line art, we may overflood it in sample merge (which
would use color in the line art computation). And if having all colors
on the same layer, this would go over other colors (making the wrong
impression that the line art leaked).
This new option is mostly to keep some control over the mask growth.
Usually a few pixels is enough for most styles of drawing (though we
could technically allow for very wide strokes).
This commit is contained in:
Jehan 2018-11-22 18:13:58 +01:00
parent dd3d9ab3dd
commit eb042e6c87
11 changed files with 82 additions and 41 deletions

View File

@ -522,7 +522,7 @@ gimp_channel_select_fuzzy (GimpChannel *channel,
select_transparent,
select_criterion,
diagonal_neighbors,
0.92, /* TODO */
0.92, 3, /* TODO */
x, y);
if (! sample_merged)

View File

@ -58,7 +58,8 @@ gimp_drawable_bucket_fill (GimpDrawable *drawable,
gdouble threshold,
gboolean sample_merged,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gfloat line_art_stroke_threshold,
gint line_art_max_grow,
gdouble seed_x,
gdouble seed_y)
{
@ -79,7 +80,8 @@ gimp_drawable_bucket_fill (GimpDrawable *drawable,
fill_transparent, fill_criterion,
threshold, sample_merged,
diagonal_neighbors,
stroke_threshold,
line_art_stroke_threshold,
line_art_max_grow,
seed_x, seed_y, NULL,
&mask_x, &mask_y, &width, &height);
@ -146,6 +148,7 @@ gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawable,
gboolean sample_merged,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gint max_grow,
gdouble seed_x,
gdouble seed_y,
GeglBuffer **mask_buffer,
@ -208,6 +211,7 @@ gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawable,
fill_criterion,
diagonal_neighbors,
stroke_threshold,
max_grow,
(gint) seed_x,
(gint) seed_y);
if (mask_buffer && *mask_buffer)

View File

@ -29,7 +29,8 @@ void gimp_drawable_bucket_fill (GimpDrawable *drawabl
gdouble threshold,
gboolean sample_merged,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gfloat line_art_stroke_threshold,
gint line_art_max_grow,
gdouble x,
gdouble y);
GeglBuffer * gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawable,
@ -42,7 +43,8 @@ GeglBuffer * gimp_drawable_get_bucket_fill_buffer (GimpDrawable *drawabl
gdouble threshold,
gboolean sample_merged,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gfloat line_art_stroke_threshold,
gint line_art_max_grow,
gdouble seed_x,
gdouble seed_y,
GeglBuffer **mask_buffer,

View File

@ -50,7 +50,8 @@ typedef struct
{
gint x;
gint y;
gfloat dist;
gfloat radius;
gint level;
} BorderPixel;
@ -126,7 +127,8 @@ static void line_art_result_free (GimpPickableLineArtAsyncResult
static void line_art_queue_pixel (GQueue *queue,
gint x,
gint y,
gfloat dist);
gfloat radius,
gint level);
/* public functions */
@ -311,6 +313,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
GimpSelectCriterion select_criterion,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gint flooding_max,
gint x,
gint y)
{
@ -449,14 +452,14 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y - 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
ny = y;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
if (y < height - 1)
@ -464,7 +467,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y + 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
@ -477,14 +480,14 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y - 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
ny = y;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
if (y < height - 1)
@ -492,7 +495,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y + 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
@ -503,7 +506,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y - 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
@ -512,7 +515,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = y + 1;
if (mask[nx + ny * width] != 0.0)
{
line_art_queue_pixel (queue, x, y, thickness);
line_art_queue_pixel (queue, x, y, thickness, 1);
continue;
}
}
@ -526,6 +529,9 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
if (mask[c->x + c->y * width] != 1.0)
{
mask[c->x + c->y * width] = 1.0;
if (c->level >= flooding_max)
/* Do not overflood under line arts. */
continue;
if (c->x > 0)
{
nx = c->x - 1;
@ -534,21 +540,21 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = c->y - 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
ny = c->y;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
if (c->y < height - 1)
{
ny = c->y - 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
}
if (c->x < width - 1)
@ -559,21 +565,21 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = c->y - 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
ny = c->y;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
if (c->y < height - 1)
{
ny = c->y - 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
}
nx = c->x;
@ -582,16 +588,16 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
ny = c->y - 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
if (c->y < height - 1)
{
ny = c->y + 1;
if (mask[nx + ny * width] == 0.0 &&
distmap[nx + ny * width] > distmap[c->x + c->y * width] &&
distmap[nx + ny * width] < c->dist)
line_art_queue_pixel (queue, nx, ny, c->dist);
distmap[nx + ny * width] < c->radius)
line_art_queue_pixel (queue, nx, ny, c->radius, c->level + 1);
}
}
g_free (c);
@ -1206,13 +1212,15 @@ static void
line_art_queue_pixel (GQueue *queue,
gint x,
gint y,
gfloat dist)
gfloat radius,
gint level)
{
BorderPixel *p = g_new (BorderPixel, 1);
p->x = x;
p->y = y;
p->dist = dist;
p->radius = radius;
p->level = level;
g_queue_push_head (queue, p);
}

View File

@ -37,14 +37,15 @@ GimpAsync * gimp_pickable_contiguous_region_prepare_line_art_async (GimpPickabl
GeglBuffer * gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
GeglBuffer *line_art,
gfloat *distmap,
gfloat *thickmap,
gfloat *line_art_distmap,
gfloat *line_art_thickmap,
gboolean antialias,
gfloat threshold,
gboolean select_transparent,
GimpSelectCriterion select_criterion,
gboolean diagonal_neighbors,
gfloat stroke_threshold,
gfloat line_art_stroke_threshold,
gint line_art_max_grow,
gint x,
gint y);

View File

@ -171,7 +171,7 @@ drawable_edit_bucket_fill_invoker (GimpProcedure *procedure,
GIMP_PDB_CONTEXT (context)->sample_threshold,
GIMP_PDB_CONTEXT (context)->sample_merged,
GIMP_PDB_CONTEXT (context)->diagonal_neighbors,
0.92, /* TODO */
0.92, 3, /* TODO */
x, y);
}
else

View File

@ -54,6 +54,7 @@ enum
PROP_ANTIALIAS,
PROP_THRESHOLD,
PROP_LINE_ART_THRESHOLD,
PROP_LINE_ART_MAX_GROW,
PROP_FILL_CRITERION
};
@ -64,6 +65,7 @@ struct _GimpBucketFillOptionsPrivate
GtkWidget *threshold_scale;
GtkWidget *line_art_threshold_scale;
GtkWidget *line_art_grow_scale;
};
static void gimp_bucket_fill_options_config_iface_init (GimpConfigInterface *config_iface);
@ -162,6 +164,13 @@ gimp_bucket_fill_options_class_init (GimpBucketFillOptionsClass *klass)
0.0, 1.0, 0.92,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_INT (object_class, PROP_LINE_ART_MAX_GROW,
"line-art-max-grow",
_("Maximum growing size"),
_("Maximum number of pixels grown under the line art"),
1, 100, 3,
GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_FILL_CRITERION,
"fill-criterion",
_("Fill by"),
@ -219,6 +228,9 @@ gimp_bucket_fill_options_set_property (GObject *object,
case PROP_LINE_ART_THRESHOLD:
options->line_art_threshold = g_value_get_double (value);
break;
case PROP_LINE_ART_MAX_GROW:
options->line_art_max_grow = g_value_get_int (value);
break;
case PROP_FILL_CRITERION:
options->fill_criterion = g_value_get_enum (value);
gimp_bucket_fill_options_update_criterion (options);
@ -264,6 +276,9 @@ gimp_bucket_fill_options_get_property (GObject *object,
case PROP_LINE_ART_THRESHOLD:
g_value_set_double (value, options->line_art_threshold);
break;
case PROP_LINE_ART_MAX_GROW:
g_value_set_int (value, options->line_art_max_grow);
break;
case PROP_FILL_CRITERION:
g_value_set_enum (value, options->fill_criterion);
break;
@ -305,9 +320,11 @@ gimp_bucket_fill_options_update_criterion (GimpBucketFillOptions *options)
gtk_widget_hide (options->priv->threshold_scale);
gtk_widget_show (options->priv->line_art_threshold_scale);
gtk_widget_show (options->priv->line_art_grow_scale);
break;
default:
gtk_widget_hide (options->priv->line_art_threshold_scale);
gtk_widget_hide (options->priv->line_art_grow_scale);
gtk_widget_show (options->priv->antialias_checkbox);
gtk_widget_show (options->priv->diagonal_neighbors_checkbox);
@ -404,6 +421,13 @@ gimp_bucket_fill_options_gui (GimpToolOptions *tool_options)
options->priv->threshold_scale = scale;
gtk_widget_show (scale);
/* Line Art: max growing size */
scale = gimp_prop_spin_scale_new (config, "line-art-max-grow", NULL,
1, 5, 0);
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
options->priv->line_art_grow_scale = scale;
gtk_widget_show (scale);
/* Line Art: stroke threshold */
scale = gimp_prop_spin_scale_new (config, "line-art-threshold", NULL,
0.05, 0.1, 2);

View File

@ -47,6 +47,7 @@ struct _GimpBucketFillOptions
gdouble threshold;
gdouble line_art_threshold;
gint line_art_max_grow;
GimpSelectCriterion fill_criterion;

View File

@ -398,6 +398,7 @@ gimp_bucket_fill_tool_preview (GimpBucketFillTool *tool,
options->sample_merged,
options->diagonal_neighbors,
options->line_art_threshold,
options->line_art_max_grow,
x, y, &tool->priv->fill_mask,
&x, &y, NULL, NULL);
if (line_art)

View File

@ -128,6 +128,6 @@ gimp_fuzzy_select_tool_get_mask (GimpRegionSelectTool *region_select,
options->select_transparent,
options->select_criterion,
options->diagonal_neighbors,
0.92, /* TODO */
0.92, 3, /* TODO */
x, y);
}

View File

@ -175,7 +175,7 @@ HELP
GIMP_PDB_CONTEXT (context)->sample_threshold,
GIMP_PDB_CONTEXT (context)->sample_merged,
GIMP_PDB_CONTEXT (context)->diagonal_neighbors,
0.92, /* TODO */
0.92, 3, /* TODO */
x, y);
}
else