1. 01 Dec, 2018 6 commits
    • Ell's avatar
      app: #include <string.h> in gimp-scratch.h · 8c9eb1c7
      Ell authored
      ... for memset().
      8c9eb1c7
    • Ell's avatar
      5d1a79a3
    • Ell's avatar
      app: add scratch-total variable to the dashboard · 698d1af7
      Ell authored
      Add a scratch-total variable to the dashboard's misc group, showing
      the total amount of memory used by the scratch allocator.
      698d1af7
    • Ell's avatar
      app: add gimp-scratch allocator · a8a86552
      Ell authored
      gimp-scratch is a fast memory allocator (on the order of magnitude
      of alloca()), suitable for small (up to a few megabytes), short-
      lived (usually, bound to the current stack-frame) allocations.
      Unlike alloca(), gimp-scratch doesn't use the stack, and is
      therefore safer, and will also serve bigger requests, by falling-
      back to malloc().
      
      The allocator itself is very simple:  We keep a per-thread stack of
      cached memory blocks (allocated using the normal allocator).  When
      serving an allocation request, we simply pop the top block off the
      stack, and return it. If the block is too small, we replace it with
      a big-enough block.  When the block is freed, we push it back to
      the top of the stack (note that even though each thread uses a
      separate stack, blocks can be migrated between threads, i.e.,
      allocated on one thread, and freed on another thread, although this
      is not really an intended usage pattern.)  The idea is that the
      stacks will ultimately stabalize to contain blocks that can serve
      all the encountered allocation patterns, without needing to reisze
      any of the blocks; as a consequence, the amount of scratch memory
      allocated at any given time should really be kept to a minimum.
      a8a86552
    • Ell's avatar
      app: in GimpBacktrace Linux backend, don't leak backtrace when dropping threads · 01f94099
      Ell authored
      Should have been part of commit
      a29d040d.
      01f94099
    • Ell's avatar
  2. 30 Nov, 2018 2 commits
    • Ell's avatar
      app: add gimp_async_add_callback_for_object() · 49fd2847
      Ell authored
      ... which is similar to gimp_async_add_callback(), taking an
      additional GObject argument.  The object is kept alive for the
      duration of the callback, and the callback is automatically removed
      when the object is destroyed (if it hasn't been already called).
      
      This is analogous to g_signal_connect_object(), compared to
      g_signal_connect().
      49fd2847
    • Ell's avatar
      app: unref async when removing last callback if idle is pending · a779dd38
      Ell authored
      In gimp_async_remove_callback(), if removing the last callback
      while the callback idle-source is already pending, cancel the idle
      source and unref the async object (the async is reffed when adding
      the idle source.)
      a779dd38
  3. 29 Nov, 2018 2 commits
  4. 28 Nov, 2018 4 commits
    • Ell's avatar
      app: use gimp_tile_handler_validate_validate() in GimpProjection · d6f0ca55
      Ell authored
      Use gimp_tile_handler_validate_validate(), added in the last
      commit, in GimpProjection, in order to render the projection,
      instead of separately invalidating the buffer, undoing the
      invalidation, and then rendering the graph.  This is more
      efficient, and more idiomatic.
      d6f0ca55
    • Ell's avatar
      app: add GimpTileHandlerValidate::{begin,end}_validate() vfuncs · 5a623fc5
      Ell authored
      Add begin_validate() and end_validate() virtual functions, and
      corresponding free functions, to GimpTileHandlerValidate.  These
      functions are called before/after validation happens, and should
      perform any necessary steps to prepare for validation.  The default
      implementation suspends validation on tile access, so that the
      assigned buffer may be accessed without causing validation.
      
      Implement the new functions in GimpTileHandlerProjectable, by
      calling gimp_projectable_begin_render() and
      gimp_projectable_end_render(), respectively, instead of calling
      these functions in the ::validate() implementation (which, in turn,
      allows us to use the default ::validate() implementation.)
      
      In GimpProjection, use the new functions in place of
      gimp_projectable_{begin,end}_render().
      5a623fc5
    • Ell's avatar
      app: avoid starting the chunk renderer while finishing drawing a projection · 8a47b681
      Ell authored
      In gimp_projection_finish_draw(), make sure we don't accidentally
      re-start the chunk renderer idle source while running the remaining
      iterations, in case the chunk height changes, and we need to reinit
      the renderer state.
      8a47b681
    • Ell's avatar
      app: avoid flushing bufferless projections · b07f8102
      Ell authored
      Don't needlessly flush projections whose buffer hasn't been
      allocated yet.  This can happen when opening an image, in which
      case the image is flushed before its projection has a buffer.
      b07f8102
  5. 27 Nov, 2018 2 commits
    • Jehan's avatar
      app: flood isolated pixels in smart colorization fill. · 744d6793
      Jehan authored
      The smart colorization was leaving irritating single pixels in between
      colorized regions, after growing and combining. So let's just flood
      these. We don't flood bigger regions (and in particular don't use
      gimp_gegl_apply_flood()) on purpose, because there may be small yet
      actual regions inside regions which we'd want in other colors. 1-pixel
      regions is the extreme case where chances that one wanted it filled are
      just higher.
      744d6793
    • Jehan's avatar
      app: radius map actually not useful during smart colorization grow step. · 6bec0bc8
      Jehan authored
      The distance map has all the information we need already. Also we will
      actually grow up to the max radius pixel (middle pixel of a stroke).
      After discussing with Aryeom, we realized it was better to fill a stroke
      fully (for cases of overflowing, I already added the "Maximum growing
      size" property anyway).
      6bec0bc8
  6. 26 Nov, 2018 3 commits
  7. 22 Nov, 2018 3 commits
    • Jehan's avatar
      app: add "line-art-max-grow" property to the bucket fill options. · eb042e6c
      Jehan authored
      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).
      eb042e6c
    • Jehan's avatar
      app: properly (bucket) fill created splines and segments in line art. · 5a4754f3
      Jehan authored
      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.
      5a4754f3
    • Jehan's avatar
      app: replace gegl:watershed-transform with custom algorithm. · 3467acf0
      Jehan authored
      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.
      3467acf0
  8. 20 Nov, 2018 1 commit
    • Jehan's avatar
      app: priority map now unneeded for gegl:watershed-transform. · 963eef82
      Jehan authored
      This commit is based on GEGL master as I just made the auxiliary buffer
      of gegl:watershed-transform optional for basic cases.
      It doesn't necessarily makes the whole operation that much faster
      according to my tests, but it makes the code simpler as creating this
      priority map was quite unnecessary.
      963eef82
  9. 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
  10. 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
  11. 15 Nov, 2018 1 commit
  12. 14 Nov, 2018 9 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