1. 19 Nov, 2018 6 commits
    • Ell's avatar
      app: add gimp_pickable_contiguous_region_prepare_line_art_async() ... · b4e12fbb
      Ell authored
      ... and use in bucket-fill tool
      
      Add gimp_pickable_contiguous_region_prepare_line_art_async(), which
      computes a line-art asynchronously, and use it in the bucket-fill
      tool, instead of having the tool create the async op.
      
      This allows the async to keep running even after the pickable dies,
      since we only need the pickable's buffer, and not the pickable
      itself.  Previously, we reffed the pickable for the duration of the
      async, but we could still segfault when unreffing it, if the
      pickable was a drawable, and its parent image had already died.
      
      Furthermore, let the async work on a copy of the pickable's buffer,
      rather than the pickable's buffer directly.  This avoids some race
      conditions when the pickable is the image (i.e., when "sample
      merged" is active), since then we're using image projection's
      buffer, which is generally unsafe to use in different threads
      concurrently.
      
      Also, s/! has_alpha/has_alpha/ when looking for transparent pixels,
      and quit early, at least during this stage, if the async in
      canceled.
      b4e12fbb
    • Ell's avatar
      app: in gimp-parallel, boost priority of waited-upon asyncs · 62baffed
      Ell authored
      When an async that was created through
      gimp_parallel_run_async[_full](), and whose execution is still
      pending, is being waited-upon, maximize its priority so that it
      gets executed before all other pending asyncs.
      
      Note that we deliberately don't simply execute the async in the
      calling thread in this case, to allow timed-waits to fail (which is
      especially important for gimp_wait()).
      62baffed
    • Ell's avatar
      app: add GimpAsync::waiting signal · 965da12b
      Ell authored
      ... which is emitted when the async is being waited-upon, blocking
      execution.
      965da12b
    • Jehan's avatar
    • Jehan's avatar
      app: better handle drawable and image update for line art computation. · 04726533
      Jehan authored
      The "update" signal on drawable or projection can actually be emitted
      many times for a single painting event. Just add new signals ("painted"
      on GimpDrawable and "rendered" on GimpProjection) which are emitted once
      for a single update (from user point of view), at the end, after actual
      rendering is done (i.e. after the various "update" signals).
      
      Also better support the sample merge vs current drawable paths for
      bucket fill.
      04726533
    • Jehan's avatar
      app: remove now useless erosion size option. · 3f58a385
      Jehan authored
      Since commit b00037b8, erosion size is not used anymore, as this step
      has been removed, and the end point detection now uses local thickness
      of strokes instead.
      3f58a385
  2. 16 Nov, 2018 1 commit
    • Jehan's avatar
      app: improve end point detection for smart colorization. · b00037b8
      Jehan authored
      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.
      b00037b8
  3. 15 Nov, 2018 1 commit
  4. 14 Nov, 2018 20 commits
    • Ell's avatar
      app: more gimp-parallel fixes · 05a4437d
      Ell authored
      Fix indentation in gimp-parallel.{cc,h}.
      
      Remove unused typedefs in gimp-parallel.h.
      
      s/Gimp/Gegl/ in function-type cast in gimphistogram.c.
      05a4437d
    • Ell's avatar
      app: indentation fix in gimp-parallel.cc · 115fc174
      Ell authored
      115fc174
    • Ell's avatar
      app: remove gimp_parallel_distribute(); use gegl_parallel_distribute() · 2736cee5
      Ell authored
      The parallel_distribute() family of functions has been migrated to
      GEGL.  Remove the gimp_parallel_distribute() functions from
      gimp-parallel, and replace all uses of these functions with the
      corresponding gegl_parallel_distrubte() functions.
      2736cee5
    • Jehan's avatar
      app: edit the bucket fill tool options with new line art options. · 824af124
      Jehan authored
      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).
      824af124
    • Jehan's avatar
      app: bucket fill tool with a "paint-style" interaction. · e1c40506
      Jehan authored
      Rather than just having a click interaction, let's allow to "paint" with
      the bucket fill. This is very useful for the new "line art" colorization
      since it tends to over-segment the drawing. Therefore being able to
      stroke through the canvas (rather than click, up, move, click, etc.)
      makes the process much simpler. This is also faster since we don't have
      to recompute the line art while a filling is in-progress.
      Note that this new behavior is not only for the line art mode, but also
      any other fill criterion, for which it can also be useful.
      
      Last change of behavior as a side effect: it is possible to cancel the
      tool changes the usual GIMP way (for instance by right clicking when
      releasing the mouse button).
      e1c40506
    • Jehan's avatar
      app: compute line art in advance. · f246f404
      Jehan authored
      Right now, this is mostly meaningless as it is still done sequentially.
      But I am mostly preparing the field to pre-compute the line art as
      background thread.
      f246f404
    • Jehan's avatar
      app: fix line art labellization. · 93a49951
      Jehan authored
      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.
      93a49951
    • Jehan's avatar
      app: better use GeglBufferIterator! · c4ff8154
      Jehan authored
      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.
      c4ff8154
    • Jehan's avatar
      app: directly update the mask buffer with gegl_node_blit_buffer(). · f02993fb
      Jehan authored
      No need to create a temporary buffer for this.
      f02993fb
    • Jehan's avatar
      app: create a simple priority map for line art selection flooding. · 410c7475
      Jehan authored
      We actually don't need to compute distance map. I just make the simplest
      priority map, with 1 any line art pixel and 0 any other pixel (in mask
      or not), lowest priority being propagated first.
      And let the flooding begin!
      410c7475
    • Jehan's avatar
      app: with recent gegl:watershed-transform, no need for intermediate... · e905ea7b
      Jehan authored
      ... labels buffer.
      We can watershed directly the mask buffer being correctly flagged.
      This commit relies on merge request gegl!8 being accepted and merged.
      e905ea7b
    • Jehan's avatar
      app: use char array for temporary data (rather than a GEGL buffer). · 0c80f8a7
      Jehan authored
      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.
      0c80f8a7
    • Jehan's avatar
      app: use simpler allocated variables. · f975f15e
      Jehan authored
      Allocating double-level arrays is just very inefficient.
      f975f15e
    • Jehan's avatar
      f19181dc
    • Jehan's avatar
      app: fix stroke labels in gimp_lineart_estimate_stroke_width(). · 910d7934
      Jehan authored
      I must make sure that stroke pixels are labelled 0 and non-stroke other
      than 0.
      910d7934
    • Jehan's avatar
      app: use more GeglBufferIterator. · 1822ea39
      Jehan authored
      In this case, it makes the code a bit more messy, but hopefully more
      efficient.
      1822ea39
    • Jehan's avatar
    • Jehan's avatar
      fcd038eb
    • Jehan's avatar
      app: implement second step for line art selection/filling. · 8502b4e7
      Jehan authored
      When filling colors in line arts, you don't want to leave space between
      the strokes and the color, which usually happen with any of the current
      selection methods.
      A "KISS" trick is usually to grow your selection a few pixels before
      filling (adding an additional step in colorization process), which
      obviously does not handle all cases (depending on drawing style and
      stroke size, you may need to grow more or less) as it doesn't take into
      account actual stroke geometry.
      
      Instead, I label the selection and the "rest" differently and leave the
      pixel strokes unlabelled. Then I let these unlabelled pixels be flooded
      by the "gegl:watershed-transform" operation.
      Note that this second step is different from the second step from the
      GREYC research paper, as they use their own watershed algorithm taking
      color spots as sources to color the whole image at once. This is a
      different workflow from the one using bucket fill with a single color
      source.
      8502b4e7
    • Jehan's avatar
      app, libgimpbase: add GIMP_SELECT_CRITERION_LINE_ART selection type. · 8ed12b1b
      Jehan authored
      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.
      8ed12b1b
  5. 11 Nov, 2018 1 commit
    • Ell's avatar
      Issue #2473 - Transforming a layer doesn't properly transform its mask · 45fc30ca
      Ell authored
      In gimp_drawable_transform_buffer_affine(), avoid modifying the
      clipping mode when transforming layer masks, since this function is
      used (among other things) to transform layer masks together with
      their layer, in which case they should use the same clipping mode
      as the layer.
      
      This fixes a regression introduced by commit
      2ae823ba, causing layer masks to be
      transformed with a mismatched clipping mode during layer
      transforms, leading to discrepencies between the transformed layer
      and the transformed mask.
      
      This commit merely reverts the necessary part of above commit,
      fixing the regression, though note that this code is really up for
      some serious refactoring: the logic for determining which clipping
      mode to use when is spread all over the place.
      45fc30ca
  6. 07 Nov, 2018 1 commit
    • Ell's avatar
      app: a few improvements to the GimpBacktrace Linux backend · a29d040d
      Ell authored
      Blacklist the "threaded-ml" thread, which seems to mask the
      backtrace signal.
      
      Improve signal-handler synchronozation, to avoid segfaulting when
      giving up on waiting for all threads to handle the signal.
      Furthermore, when one or more threads fail to handle the signal in
      time, return a GimpBacktrace instance with backtraces for all the
      other threads, and with empty backtraces for all the non-responding
      threads, instead of returning NULL and leaking the allocated
      instance.  Don't blacklist threads that failed to handle the signal
      in time, and instead shorten the wait period for handling the
      signal, and yield execution during waiting to lower the CPU usage.
      a29d040d
  7. 04 Nov, 2018 1 commit
    • Ell's avatar
      app: don't let image component mask affect channel colors · 56920dcd
      Ell authored
      Connect GimpImage's gimp:mask-components node to the layers node
      *before* connecting the channels node, so that the image's
      component mask doesn't affect the channel colors, as is the case in
      2.8.
      56920dcd
  8. 27 Oct, 2018 1 commit
    • Ell's avatar
      Issue #2405 - Rotation center shifts by half a pixel ... · c271992a
      Ell authored
      ... the second time you do a 180 degrees rotation
      
      In gimp_transform_resize_adjust(), nudge the transformed layer
      boundary by EPSILON toward the center, to avoid enlarging the layer
      unnecessarily, as a result of numeric error amplified by rounding,
      when the tranformed boundary should land on integer coordinates.
      In particular, this avoids enlarging the layer when rotating by 180
      degrees.
      c271992a
  9. 25 Oct, 2018 1 commit
    • Michael Natterer's avatar
      Issue #2235 - Color reset/swap keyboard shortcuts not discoverable... · ae9d84dd
      Michael Natterer authored
      ...via hover tooltips
      
      Use the GtkWidget::query_tooltip() signal on GimpFgBgEditor to emit an
      own signal "tooltip" that has the hovered widget area as parameter.
      
      Connect to GimpFgBgEditor::tooltip() in gimptoolbox-color-area.c and
      set separate tooltips on the widget's areas, including the shortcuts
      for "Swap colors" and "Default colors".
      ae9d84dd
  10. 23 Oct, 2018 1 commit
    • Elle Stone's avatar
      Issue #2345 - Add xyY to color sample readouts · 298cc570
      Elle Stone authored
      Add xyY color space to the color spaces for sampling colors.
      
      Also add code to xcf-load.c that makes sure the sample point loading
      code handles unknown future GimpColorPickMode values (fall back to
      PIXEL pick mode).
      298cc570
  11. 22 Oct, 2018 1 commit
  12. 11 Oct, 2018 1 commit
    • Ell's avatar
      app: always use libunwind for symbol names in GimpBacktrace Linux backend · 72fc0174
      Ell authored
      In the GimpBacktrace Linux backend, always use libunwind, when
      available, to find symbol names, even if dladdr() or libbacktrace
      had already found one.  libunwind provides more descriptive names
      in certain cases, and, in particular, full symbol names for C++
      lambdas.
      
      Note that, in some cases, this can result in a discrepancy between
      the reported symbol name, and the corresponding source location.
      72fc0174
  13. 10 Oct, 2018 3 commits
    • Ell's avatar
      app: in GimpBacktrace Windows backend, avoid bogus symbol addresses · 52772cf3
      Ell authored
      In the GimpBacktrace Windows backend, avoid reporting meaningless
      symbol addresses when failing to retrieve meaningful ones.
      Unfortunately, it seems that we never get symbol addresses for
      symbols that have debug information, which negatively affects the
      log viewer's call graph.  We're going to have to work around this.
      52772cf3
    • Ell's avatar
      app: in GimpBacktrace Windows backend, set main-thread name · 52908f39
      Ell authored
      When initializing the GimpBacktrace Windows backend, set the name
      of the current thread (which is assumed to be the main thread) to
      the program's name, to match its name on Linux.  We normally rely
      on the SET_THREAD_NAME exception to set thread names on Windows,
      which isn't raised for the main thread.
      52908f39
    • Ell's avatar
      app: improve description comment of GimpAsync · ca6e4eb4
      Ell authored
      ca6e4eb4
  14. 09 Oct, 2018 1 commit
    • Ell's avatar
      app: allow progressive execution of parallel async operations · 4969d757
      Ell authored
      In the gimp_parallel_run_async() family of functions, allow the
      async callback to return without completing the async operation, in
      which case the callback will be called again, until the operation
      is either completed, or canceled, in which case it is aborted
      (previously, returning from the callback without completing the
      operation would cause it to be aborted.)  It is guaranteed that all
      operations of the same priority will get a chance to run, even if
      some of them contuinuosly return without completing.
      
      This allows potentially time-consuming operations to yield
      execution in favor of other same-priority operations, and, in
      particular, of higher-priority operations, to avoid priority
      inversion.  Essentially, this allows a simple form of cooperative
      multitasking among async operations.
      4969d757