From 5a4754f32b8e08f71d8cb521acdf45bdbc0e802a Mon Sep 17 00:00:00 2001 From: Jehan Date: Thu, 22 Nov 2018 14:32:59 +0100 Subject: [PATCH] app: properly (bucket) fill created splines and segments in line art. For this, I needed distmap of the closed version of the line art (after splines and segments are created). This will result in invisible stroke borders added when flooding in the end. These invisible borders will have a thickness of 0.0, which means that flooding will stop at once after these single pixels are filled, which makes it quick, and is perfect since created splines and segments are 1-pixel thick anyway. Only downside is having to run "gegl:distance-transform" a second time, but this still stays fast. --- app/core/gimplineart.c | 44 +++++++++++++++++------ app/core/gimppickable-contiguous-region.c | 6 ++-- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/app/core/gimplineart.c b/app/core/gimplineart.c index c8373eb87c..4c9648262f 100644 --- a/app/core/gimplineart.c +++ b/app/core/gimplineart.c @@ -105,8 +105,7 @@ static GArray * gimp_lineart_line_segment_until_hit (const GeglBuffer Pixel start, GimpVector2 direction, int size); -static gfloat * gimp_lineart_estimate_strokes_radii (GeglBuffer *mask, - gfloat **lineart_distmap); +static gfloat * gimp_lineart_estimate_strokes_radii (GeglBuffer *mask); /* Some callback-type functions. */ @@ -188,7 +187,7 @@ static void gimp_edgelset_next8 (const GeglBuffer *buffer, * @segments_max_length: the maximum length for creating segments * between end points. Unlike splines, segments * are straight lines. - * @lineart_distmap: a distance map of the line art pixels. + * @closed_distmap: a distance map of the closed line art pixels. * @lineart_radii: a map of estimated radii of line art border pixels. * * Creates a binarized version of the strokes of @buffer, detected either @@ -224,7 +223,7 @@ gimp_lineart_close (GeglBuffer *buffer, gint created_regions_minimum_area, gboolean small_segments_from_spline_sources, gint segments_max_length, - gfloat **lineart_distmap, + gfloat **closed_distmap, gfloat **lineart_radii) { const Babl *gray_format; @@ -313,7 +312,7 @@ gimp_lineart_close (GeglBuffer *buffer, smoothed_curvatures, normal_estimate_mask_size); - radii = gimp_lineart_estimate_strokes_radii (strokes, lineart_distmap); + radii = gimp_lineart_estimate_strokes_radii (strokes); threshold = 1.0f - end_point_rate; clamped_threshold = MAX (0.25f, threshold); for (i = 0; i < width; i++) @@ -457,6 +456,33 @@ gimp_lineart_close (GeglBuffer *buffer, point++; } + if (closed_distmap) + { + GeglNode *graph; + GeglNode *input; + GeglNode *op; + + /* Flooding needs a distance map for closed line art. */ + *closed_distmap = g_new (gfloat, width * height); + + graph = gegl_node_new (); + input = gegl_node_new_child (graph, + "operation", "gegl:buffer-source", + "buffer", closed, + NULL); + op = gegl_node_new_child (graph, + "operation", "gegl:distance-transform", + "metric", GEGL_DISTANCE_METRIC_EUCLIDEAN, + "normalize", FALSE, + NULL); + gegl_node_connect_to (input, "output", + op, "input"); + gegl_node_blit (op, 1.0, gegl_buffer_get_extent (closed), + NULL, *closed_distmap, + GEGL_AUTO_ROWSTRIDE, GEGL_BLIT_DEFAULT); + g_object_unref (graph); + } + g_hash_table_destroy (visited); g_array_free (keypoints, TRUE); g_object_unref (strokes); @@ -1276,8 +1302,7 @@ gimp_lineart_line_segment_until_hit (const GeglBuffer *mask, } static gfloat * -gimp_lineart_estimate_strokes_radii (GeglBuffer *mask, - gfloat **lineart_distmap) +gimp_lineart_estimate_strokes_radii (GeglBuffer *mask) { GeglBufferIterator *gi; gfloat *dist; @@ -1422,10 +1447,7 @@ gimp_lineart_estimate_strokes_radii (GeglBuffer *mask, } } - if (lineart_distmap) - *lineart_distmap = dist; - else - g_free (dist); + g_free (dist); g_object_unref (distmap); return thickness; diff --git a/app/core/gimppickable-contiguous-region.c b/app/core/gimppickable-contiguous-region.c index 396758e03a..ce370c391d 100644 --- a/app/core/gimppickable-contiguous-region.c +++ b/app/core/gimppickable-contiguous-region.c @@ -437,10 +437,10 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable, for (y = 0; y < height; y++) for (x = 0; x < width; x++) { - gfloat thickness = thickmap[x + y * width]; - - if (thickness > 0.0) + if (distmap[x + y * width] == 1.0) { + gfloat thickness = thickmap[x + y * width]; + if (x > 0) { nx = x - 1;