mirror of https://github.com/GNOME/gimp.git
app, libgimpbase: add GIMP_SELECT_CRITERION_LINE_ART selection type.
This commit implements part of the research paper "A Fast and Efficient Semi-guided Algorithm for Flat Coloring Line-arts" from the GREYC (the people from G'Mic). It is meant to select regions from drawn sketchs in a "smart" way, in particular it tries to close non-perfectly closed regions, which is a common headache for digital painters and colorists. The implementation is not finished as it needs some watersheding as well so that the selected area does not leave "holes" near stroke borders. The research paper proposes a new watersheding algorithm, but I may not have to implement it, as it is more focused on automatic colorization with prepared spots (instead of bucket fill-type interaction). This will be used in particular with the fuzzy select and bucket fill tools. Note that this first version is a bit slow once we get to big images, but I hope to be able to optimize this. Also no options from the algorithm are made available in the GUI yet.
This commit is contained in:
parent
85e6700aac
commit
8ed12b1b98
|
@ -363,6 +363,8 @@ libappcore_a_sources = \
|
|||
gimplayerstack.h \
|
||||
gimplayerundo.c \
|
||||
gimplayerundo.h \
|
||||
gimplineart.c \
|
||||
gimplineart.h \
|
||||
gimplist.c \
|
||||
gimplist.h \
|
||||
gimpmaskundo.c \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,43 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* Copyright (C) 2017 Sébastien Fourey & David Tchumperlé
|
||||
* Copyright (C) 2018 Jehan
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GIMP_LINEART__
|
||||
#define __GIMP_LINEART__
|
||||
|
||||
|
||||
GeglBuffer * gimp_lineart_close (GeglBuffer *line_art,
|
||||
gboolean select_transparent,
|
||||
gfloat stroke_threshold,
|
||||
gint erosion,
|
||||
gint minimal_lineart_area,
|
||||
gint normal_estimate_mask_size,
|
||||
gfloat end_point_rate,
|
||||
gint spline_max_length,
|
||||
gfloat spline_max_angle,
|
||||
gint end_point_connectivity,
|
||||
gfloat spline_roundness,
|
||||
gboolean allow_self_intersections,
|
||||
gint created_regions_significant_area,
|
||||
gint created_regions_minimum_area,
|
||||
gboolean small_segments_from_spline_sources,
|
||||
gint segments_max_length);
|
||||
|
||||
|
||||
#endif /* __GIMP_LINEART__ */
|
|
@ -32,6 +32,7 @@
|
|||
#include "gegl/gimp-babl.h"
|
||||
|
||||
#include "gimp-utils.h" /* GIMP_TIMER */
|
||||
#include "gimplineart.h"
|
||||
#include "gimppickable.h"
|
||||
#include "gimppickable-contiguous-region.h"
|
||||
|
||||
|
@ -115,6 +116,7 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
|
|||
gint n_components;
|
||||
gboolean has_alpha;
|
||||
gfloat start_col[MAX_CHANNELS];
|
||||
gboolean free_src_buffer = FALSE;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_PICKABLE (pickable), NULL);
|
||||
|
||||
|
@ -144,6 +146,58 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
|
|||
select_transparent = FALSE;
|
||||
}
|
||||
|
||||
if (select_criterion == GIMP_SELECT_CRITERION_LINE_ART)
|
||||
{
|
||||
/* For smart selection, we generate a binarized image with close
|
||||
* regions, then run a composite selection with no threshold on
|
||||
* this intermediate buffer.
|
||||
*/
|
||||
GIMP_TIMER_START();
|
||||
src_buffer = gimp_lineart_close (src_buffer,
|
||||
select_transparent,
|
||||
/*contour_detection_level,*/
|
||||
0.92,
|
||||
/* erosion, */
|
||||
-1,
|
||||
/*minimal_lineart_area,*/
|
||||
5,
|
||||
/*normal_estimate_mask_size,*/
|
||||
5,
|
||||
/*end_point_rate,*/
|
||||
0.85,
|
||||
/*spline_max_length,*/
|
||||
60,
|
||||
/*spline_max_angle,*/
|
||||
90.0,
|
||||
/*end_point_connectivity,*/
|
||||
2,
|
||||
/*spline_roundness,*/
|
||||
1.0,
|
||||
/*allow_self_intersections,*/
|
||||
TRUE,
|
||||
/*created_regions_significant_area,*/
|
||||
4,
|
||||
/*created_regions_minimum_area,*/
|
||||
100,
|
||||
/*small_segments_from_spline_sources,*/
|
||||
TRUE,
|
||||
/*segments_max_length*/
|
||||
20);
|
||||
free_src_buffer = TRUE;
|
||||
antialias = FALSE;
|
||||
threshold = 0.0;
|
||||
select_transparent = FALSE;
|
||||
select_criterion = GIMP_SELECT_CRITERION_COMPOSITE;
|
||||
diagonal_neighbors = FALSE;
|
||||
|
||||
format = choose_format (src_buffer, select_criterion,
|
||||
&n_components, &has_alpha);
|
||||
gegl_buffer_sample (src_buffer, x, y, NULL, start_col, format,
|
||||
GEGL_SAMPLER_NEAREST, GEGL_ABYSS_NONE);
|
||||
|
||||
GIMP_TIMER_END("close line-art");
|
||||
}
|
||||
|
||||
extent = *gegl_buffer_get_extent (src_buffer);
|
||||
|
||||
mask_buffer = gegl_buffer_new (&extent, babl_format ("Y float"));
|
||||
|
@ -161,6 +215,8 @@ gimp_pickable_contiguous_region_by_seed (GimpPickable *pickable,
|
|||
|
||||
GIMP_TIMER_END("foo");
|
||||
}
|
||||
if (free_src_buffer)
|
||||
g_object_unref (src_buffer);
|
||||
|
||||
return mask_buffer;
|
||||
}
|
||||
|
@ -297,6 +353,10 @@ choose_format (GeglBuffer *buffer,
|
|||
format = babl_format ("CIE LCH(ab) alpha float");
|
||||
break;
|
||||
|
||||
case GIMP_SELECT_CRITERION_LINE_ART:
|
||||
format = babl_format ("Y'A u8");
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
break;
|
||||
|
@ -387,6 +447,10 @@ pixel_difference (const gfloat *col1,
|
|||
max = fabs (col1[2] - col2[2]) / 360.0;
|
||||
max = MIN (max, 1.0 - max);
|
||||
break;
|
||||
|
||||
case GIMP_SELECT_CRITERION_LINE_ART:
|
||||
/* Smart selection is handled before. */
|
||||
g_return_val_if_reached (0.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +674,7 @@ find_contiguous_region (GeglBuffer *src_buffer,
|
|||
row = g_new (gfloat, gegl_buffer_get_width (src_buffer) * n_components);
|
||||
#endif
|
||||
|
||||
src_sampler = gegl_buffer_sampler_new (src_buffer,
|
||||
src_sampler = gegl_buffer_sampler_new (src_buffer,
|
||||
format, GEGL_SAMPLER_NEAREST);
|
||||
|
||||
segment_queue = g_queue_new ();
|
||||
|
|
|
@ -1666,6 +1666,7 @@ gimp_select_criterion_get_type (void)
|
|||
{ GIMP_SELECT_CRITERION_LCH_L, "GIMP_SELECT_CRITERION_LCH_L", "lch-l" },
|
||||
{ GIMP_SELECT_CRITERION_LCH_C, "GIMP_SELECT_CRITERION_LCH_C", "lch-c" },
|
||||
{ GIMP_SELECT_CRITERION_LCH_H, "GIMP_SELECT_CRITERION_LCH_H", "lch-h" },
|
||||
{ GIMP_SELECT_CRITERION_LINE_ART, "GIMP_SELECT_CRITERION_LINE_ART", "line-art" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
@ -1682,6 +1683,7 @@ gimp_select_criterion_get_type (void)
|
|||
{ GIMP_SELECT_CRITERION_LCH_L, NC_("select-criterion", "LCh Lightness"), NULL },
|
||||
{ GIMP_SELECT_CRITERION_LCH_C, NC_("select-criterion", "LCh Chroma"), NULL },
|
||||
{ GIMP_SELECT_CRITERION_LCH_H, NC_("select-criterion", "LCh Hue"), NULL },
|
||||
{ GIMP_SELECT_CRITERION_LINE_ART, NC_("select-criterion", "Line Art"), NULL },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
|
|
|
@ -1144,6 +1144,7 @@ typedef enum
|
|||
* @GIMP_SELECT_CRITERION_LCH_L: LCh Lightness
|
||||
* @GIMP_SELECT_CRITERION_LCH_C: LCh Chroma
|
||||
* @GIMP_SELECT_CRITERION_LCH_H: LCh Hue
|
||||
* @GIMP_SELECT_CRITERION_LINE_ART: Line Art
|
||||
*
|
||||
* Criterions for color similarity.
|
||||
**/
|
||||
|
@ -1164,6 +1165,7 @@ typedef enum
|
|||
GIMP_SELECT_CRITERION_LCH_L, /*< desc="LCh Lightness" >*/
|
||||
GIMP_SELECT_CRITERION_LCH_C, /*< desc="LCh Chroma" >*/
|
||||
GIMP_SELECT_CRITERION_LCH_H, /*< desc="LCh Hue" >*/
|
||||
GIMP_SELECT_CRITERION_LINE_ART, /*< desc="Line Art" >*/
|
||||
} GimpSelectCriterion;
|
||||
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ gimp_prop_enum_combo_box_new (GObject *config,
|
|||
{
|
||||
/* ditto */
|
||||
store = gimp_enum_store_new_with_values (param_spec->value_type,
|
||||
11,
|
||||
12,
|
||||
GIMP_SELECT_CRITERION_COMPOSITE,
|
||||
GIMP_SELECT_CRITERION_R,
|
||||
GIMP_SELECT_CRITERION_G,
|
||||
|
@ -546,7 +546,8 @@ gimp_prop_enum_combo_box_new (GObject *config,
|
|||
GIMP_SELECT_CRITERION_V,
|
||||
GIMP_SELECT_CRITERION_LCH_L,
|
||||
GIMP_SELECT_CRITERION_LCH_C,
|
||||
GIMP_SELECT_CRITERION_LCH_H);
|
||||
GIMP_SELECT_CRITERION_LCH_H,
|
||||
GIMP_SELECT_CRITERION_LINE_ART);
|
||||
}
|
||||
|
||||
if (store)
|
||||
|
|
|
@ -568,7 +568,8 @@ package Gimp::CodeGen::enums;
|
|||
GIMP_SELECT_CRITERION_A
|
||||
GIMP_SELECT_CRITERION_LCH_L
|
||||
GIMP_SELECT_CRITERION_LCH_C
|
||||
GIMP_SELECT_CRITERION_LCH_H) ],
|
||||
GIMP_SELECT_CRITERION_LCH_H
|
||||
GIMP_SELECT_CRITERION_LINE_ART) ],
|
||||
mapping => { GIMP_SELECT_CRITERION_COMPOSITE => '0',
|
||||
GIMP_SELECT_CRITERION_R => '1',
|
||||
GIMP_SELECT_CRITERION_G => '2',
|
||||
|
@ -579,7 +580,8 @@ package Gimp::CodeGen::enums;
|
|||
GIMP_SELECT_CRITERION_A => '7',
|
||||
GIMP_SELECT_CRITERION_LCH_L => '8',
|
||||
GIMP_SELECT_CRITERION_LCH_C => '9',
|
||||
GIMP_SELECT_CRITERION_LCH_H => '10' }
|
||||
GIMP_SELECT_CRITERION_LCH_H => '10',
|
||||
GIMP_SELECT_CRITERION_LINE_ART => '11' }
|
||||
},
|
||||
GimpSizeType =>
|
||||
{ contig => 1,
|
||||
|
|
Loading…
Reference in New Issue