Commit Graph

15 Commits

Author SHA1 Message Date
5a4754f32b 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.
2018-11-22 14:39:43 +01:00
3467acf096 app: replace gegl:watershed-transform with custom algorithm.
We don't really need to flow every line art pixel and this new
implementation is simpler (because we don't actually need over-featured
watershedding), and a lot lot faster, making the line art bucket fill
now very reactive.
For this, I am keeping the computed distance map, as well as local
thickness map around to be used when flooding the line art pixels
(basically I try to flood half the stroke thickness).

Note that there are still some issues with this new implementation as it
doesn't properly flood yet created (i.e. invisible) splines and
segments, and in particular the ones between 2 colored sections. I am
going to fix this next.
2018-11-22 14:24:52 +01:00
79571231c5 app: end point detection uses both the end point rate and clamped value. 2018-11-19 14:44:26 +01:00
3f58a38574 app: remove now useless erosion size option.
Since commit b00037b850, erosion size is not used anymore, as this step
has been removed, and the end point detection now uses local thickness
of strokes instead.
2018-11-19 14:18:18 +01:00
b00037b850 app: improve end point detection for smart colorization.
Previous algorithm was relying on strokes of small radius to detect
points of interest. In order to work with various sizes of strokes, we
were computing an approximate median stroke thickness, then using this
median value to erode the binary line art.

Unfortunately this was not working that well for very fat strokes, and
also it was potentially opening holes in the line art. These holes were
usually filled back later during the spline and segment creations. Yet
it could not be totally assured, and we had some experience where color
filling would leak out of line art zones without any holes from the
start (which is the opposite of where this new feature is supposed to
go)!

This updated code computes instead some radius estimate for every border
point of strokes, and the detection of end points uses this information
of local thickness. Using local approximation is obviously much more
accurate than a single thickness approximation for the whole drawing,
while not making the processing slower (in particular since we got rid
of the quite expensive erosion step).
This fixes the aforementionned issues (i.e. work better with fat strokes
and do not create invisible holes in closed lines), and also is not
subject to the problem of mistakenly increasing median radius when you
color fill in sample merge mode (i.e. using also the color data in the
input)!
Also it is algorithmically less intensive, which is obviously very good.

This new version of the algorithm is a reimplementation in GIMP of new
code by Sébastien Fourey and David Tschumperlé, as a result of our many
discussions and tests with the previous algorithm.

Note that we had various tests, experiments and propositions to try and
improve these issues. Skeletonization was evoked, but would have been
most likely much slower. Simpler erosion based solely on local radius
was also a possibility but it may have created too much noise (skeleton
barbs), with high curvature, hence may have created too many new
artificial endpoints.
This new version also creates more endpoints though (and does not seem
to lose any previously detected endpoints), which may be a bit annoying
yet acceptable with the new bucket fill stroking interaction. In any
case, on simple examples, it seems to do the job quite well.
2018-11-16 20:39:04 +01:00
824af12438 app: edit the bucket fill tool options with new line art options.
I have not added all the options for this new tool yet, but this sets
the base. I also added a bit of TODO for several places where we need to
make it settable, in particular the fuzzy select tool, but also simply
PDB calls (this will need to be a PDB context settings.

Maybe also I will want to make some LineArtOptions struct in order not
to have infinite list of parameters to functions. And at some point, it
may also be worth splitting a bit process with other type of
selection/fill (since they barely share any settings anyway).

Finally I take the opportunity to document a little more the parameters
to gimp_lineart_close(), which can still be improved later (I should
have documented these straight away when I re-implemented this all from
G'Mic code, as I am a bit fuzzy on some details now and will need to
re-understand code).
2018-11-14 13:37:42 +01:00
93a49951a0 app: fix line art labellization.
The older labelling based off CImg code was broken (probably because of
me, from my port). Anyway I realized what it was trying to do was too
generic, which is why we had to fix the result later (labeling all
non-stroke pixels as 0, etc.). Instead I just implemented a simpler
labelling and only look for stroke regions. It still over-label a bit
the painting but a lot less, and is much faster.
2018-11-14 13:37:42 +01:00
c4ff81540d app: better use GeglBufferIterator!
I don't actually need to loop through borders first. This is what the
abyss policy is for, and I can simply check the iterator position to
verify I am within buffer boundaries or not.
This simplifies the code a lot.
2018-11-14 13:37:42 +01:00
0c80f8a718 app: use char array for temporary data (rather than a GEGL buffer).
Also use more GeglBufferIterator on input GEGL buffer.
Using a char array is much less expensive and accelerated the line
erosion a lot!
Moving to GeglBufferIterator is not finished, but I do in steps.
2018-11-14 13:37:42 +01:00
f975f15ec0 app: use simpler allocated variables.
Allocating double-level arrays is just very inefficient.
2018-11-14 13:37:42 +01:00
f19181dcf8 app: make visited into single-level allocated array. 2018-11-14 13:37:42 +01:00
910d7934f5 app: fix stroke labels in gimp_lineart_estimate_stroke_width().
I must make sure that stroke pixels are labelled 0 and non-stroke other
than 0.
2018-11-14 13:37:42 +01:00
1822ea399a app: use more GeglBufferIterator.
In this case, it makes the code a bit more messy, but hopefully more
efficient.
2018-11-14 13:37:42 +01:00
041a8f1eec app: use GeglBufferIterator rather than gegl_buffer_sample|set(). 2018-11-14 13:37:42 +01:00
8ed12b1b98 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.
2018-11-14 13:37:42 +01:00