Anton's Students
Open, Needs TriagePublic

dkazakov created this task.Apr 21 2016, 7:16 AM
Restricted Application added a subscriber: woltherav. · View Herald TranscriptApr 21 2016, 7:16 AM

[new string, for Krita 3.1] Add workspaces as submenu in the window menu Wish: show previous color in color selector When transforming a clone layer with transform tool, create a transformation mask automatically
[renames, for Krita 3.1] Add quick flip buttons to transform docker
[UIX design needed, for 3.1] when moving the image block, show always (!) coordinates
[UIX design needed, for 3.1] List of available tag in drop down is to short in height
[UIX design needed, for 3.1] A tool that crops canvas by pixel colour

15:25 < boud>
15:25 < bugbot> KDE bug 347920 in krita (Brush engine) "Edge sharpening for circle brush tip (watercolor-like effect)" [Wishlist,Confirmed: ]
15:25 < boud>
15:26 < bugbot> KDE bug 348308 in krita (Brush engine) "Wash mode for dulling smudge brushes" [Wishlist,Confirmed: ]
15:26 < boud>
15:26 < bugbot> KDE bug 344108 in krita (Brush engine) "Feathering option for Experiment brush" [Wishlist,Confirmed: ]
15:26 < boud>
15:26 < bugbot> KDE bug 335180 in krita (Brush engine) "Extend expriment brush with outline mode." [Wishlist,Confirmed: ]
15:26 < boud>
15:26 < bugbot> KDE bug 319446 in krita (Brush engine) "Use SVG brush file as shape library for animated brush. (Alchemy pull shapes feature)" [Wishlist,Confirmed: ]
15:26 < boud>
15:26 < bugbot> KDE bug 315079 in krita (Brush engine) "Idea: add textures for experiment brush" [Wishlist,Confirmed: ]
15:27 < boud>
15:27 < bugbot> KDE bug 358183 in krita (Brush engine) "Feature request: support randomness/rotation in clone brush engine" [Wishlist,Confirmed: ]
15:28 < boud>
15:28 < bugbot> KDE bug 349459 in krita (usability) "Improvements for the reference image docker." [Wishlist,Confirmed: ]

dkazakov added a comment.EditedMay 1 2016, 11:16 AM

Suggested big projects

1. Dithering everywhere

  1. Use dithering in a display shader if the image has higher bit depth than the monitor.
    • Priority: low
    • Level: 5/5
    • Time to code: 2w
  1. Gradients
    • Priority: high
    • Level: 1/5
    • Time to code: ~1d
  1. Dithering when converting higher depth to lower depth images. Probably, a change in lcms needed?
    • Priority: low
    • Level: 3/5
    • Time to code: 2w
  1. Dithering in brush masks when painting in hi-bit depth modes
    • Priority: medium
    • Level: 4/5
    • Time to code: 1w

2. Quick brush

Our pixel brush with quadratic mask can be optimized to work 10-20 faster by just reordering of operations. The solution hides in reordering of multiplication operations and removing duplicated work. After that multithreading and SSE/AVX can be added. The project actually involves creation

  • Priority: high
  • Level: 4/5
  • Time to code: 2w + 2w (multithreading + AVX)

3. Real-looking oil-paint brush with bristles

We have a hairy brush in Krita, but the bristles can be only 1px wide there. We should extend this brush to support bigger bristles and also bristles that remove color. The problem is that the bristles should be painted extremely efficiently. Therefore, the idea of Quick Brush might be use there.

  • Priority: high
  • Level: 5/5
  • Time to code: 3-6w

4. Brush with a heightmap

Just allow brushes to paint in impasto mode. We already have an implementation of Phong Bumbmap filter, we just need a source of the height information. So the brushes should also write this info.

  • Priority: high
  • Level: 3/5
  • Time to code: 1w

5. Formula parser for all the input boxes in Krita

The user should be able to enter something like = (100px + 200cm) * 2 and the input box should automagically convert it into 'px' and pass the result to Krita. This is a nice easy project on the formal languages theory that can be implemented with a boost's lexical parser.

  • Priority: high
  • Level: 2/5
  • Time to code: < 1w

6. Watercolor painting

  • Priority: medium
  • Level: ?/5
  • Time to code: 2+w

7. openGL-based brush calculations

Just move all the calculations to the GPU. openCL doesn't work because the data transfer is too expensive.

  • Priority: medium
  • Level: 5/5
  • Time to code: 3+w

8. Sound support in Krita


  • Priority: high
  • Level: 3-5/5
  • Time to code: 2-4w
woltherav added a comment.EditedMay 1 2016, 11:50 AM

Watercolor support is 5/5, no matter what type of method you take because all existing papers are either CPU and slow, or GPU and... well, it's on the GPU, 'nuff said. Edit: Unless you are thinking of only a fringe efect, which is much smaller.

Dithering for color conversion can be a case of automating some tasks, no need to touch lcms:

  1. Blend in noise or a pattern into the existing pixel data with overlay or multiplication.
  2. Then convert.

The minor difference in pixels causes dithering during conversion because of the rounding. But it could be cool if we offer some variation in what type of pattern is baked in(like using a krita pattern :) ). Though, maybe something like proper dithering like floyd-steinberg or whatever would need modification of lcms. Not to familiar with it.

Formula parsing/sound support are kickstarter stretchgoals as well, so it might need to be considered carefully.

rempt added a subscriber: rempt.May 2 2016, 7:55 AM

For watercolor effects, all that Photoshop does is pass the stroke through a high-pass filter so you get the wet/dark fringes effect.

dkazakov added a comment.EditedMay 7 2016, 8:35 PM

1. Dithering project details

  1. Gradients

    Our gradients have low quality. See comparison to Gimp in T678. It happens due to a number of reasons.
    • we use caching in KisGradientPainter::paintGradient() see implementation of CachedGradient in the same class. It might happen that the amount of cache levels is not enough for painting smooth gradients and it should be made higher.
    • we don't use any dithering algorithm for painting gradients. Basically, we need one more wrapper over CachedGradient which adds a noise of a specified distribution and size to the input value of cachedAt() or valueAt()
    • you can find a unittest for this class in libs/image/tests/kis_gradient_painter_test.cpp
  1. Brush generation dithering

Example video:

Our brushes are just a set of rectangular images ("dabs") applied sequentially to the final image with some offset (5-10%). Each dab contains a circular image with opacity of a paraboloid-shape. Opacity is 8bit for performance reasons! Depending on the paraboloid parameters, the "steps" may appear in the final brush image. So we could try to add some randomness to the formula of mask shape generation. Right now it looks like op = opacity(\rho, \phi), so changing it into something like op = opacity(\rho + dither(\rho, ...), \phi) might to the trick.


  • we need really fast random algorithm here, because we need to calculate up to 100 MPix per second. The algorithm might be not very "random" from statistical p.o.v., but it must be extremely fast.
  • some caching system for random numbers might work, who knows?
  • what random distribution should we choose? Basically, what should be the parameters of dither(\rho, ...) function? Brush size and \rho might be related, but it shoudl be tested.

    Related classes:
  • Kis{Circle,Rectangle}MaskGenerator
  • KisCurve{Circle,Rectangle}MaskGenerator
  • KisGauss{Circle,Rectangle}MaskGenerator

    The first two classes (Kis{Circle,Rectangle}MaskGenerator) have their SSE/AVX representatives. That makes the problem a bit more complicated. See UML diagram here
dkazakov added a comment.EditedMay 7 2016, 9:03 PM

2. Quick project details

Very quick notes:

  • in Kirta we paint with "dabs"
  • all the painted dabs overlap with more than 80-90% of their area. Therefore, if we stop iterating pixels in a per-dab basis, but start grouping the dabs in sets of, say, 10, and calculate pixels for the united area, then we can get the gain up to 10x times.
  • the blending of the opacity channel should also be simplified. Basic composite "over" is really slow, so we should use some "simplified" approach. This might be one of the topics of the scientific research.
  • the main question of the research: can we use dynamically changing opacity for the strokes?

Here is a proof of concept implementation patch of this feature: patch. It doesn't apply over Krita 3.0 (only oven Krita 2.9), but I'm going to port it into a separate branch soon (Tuesday, 10.05.16 or later)
Demo video: link

3. Heightmap project details

  • we already have a Phong Bumpmap filter (Filter->Map->Phong Bumpmap)
  • but we don't have a reliable source of paint height information anywhere.

Proposed solution:

  1. Create a special HeightF32 or HeightF16 or HeightU16 color space based on KoAlphaColorSpace (which is 8-bit one). This is basically a matter of changing a template parameter and writing corresponding composite ops.
  2. Main scientific research: how to blend the paint height into the height channel? Should it be a basic Composite Over or something special? Should there be a special parameter like "paint viscosity", which defines how "dry" or "wet" the paint is?
  3. Create a special mask type: Heightmask (see KisMask, KisLayer) containing a single paint device (KisPaintDevice) object of your HeightF32 colorspace.
  4. Modify KisBrushOp paint engine to deal with this special height mask. Or embed this algorithm into KisIndirectPaintingSupport merging capabilities. The latter might probably be the easiest approach.
  5. If the latter approach is used, the two places should be modified: KisIndirectPaintingSupport::mergeToLayerImpl and KisPaintLayer::copyOriginalToProjection.
  6. Create a GUI for the feature
  7. Profit!

Example images:

4. Watercolor Painting Project

Inspiration: link1, link2

  1. Implement a filter that emulates watercolor effect on a fixed image. It should detect the edges and make the make the contour of the brush more contrast (based on KisFilter)
  2. Design GUI and user interactions for the tool.
  3. Implement filtering of the layer in a per-stroke basis. The filtering should happen in KisPaintLayer::copyOriginalToProjection() and KisIndirectPaintingSupport::mergeToLayerImpl().
  4. Given that edge-detection filter is not local (depends on the neighboring pixels), implement, KisPaintLayer::outgoingChangeRect() and probably(?) KisPaintLayer::needRect() to handle the border effects.
  5. Implement the GUI

5. Painterly color mixing

  1. Implement a draft of RYB color space that is tightly linked to a specific RGB color space. In the draft it can be linked to sRGB
    • see KoColorSpaceAlpha for an example
  2. Let the painters test the destination color space if it feels natural to them.
  3. (A) If people like it, just finish implementing the color space by letting RGB profiles be attached to it
  4. (B) If people don't like it, or if using this color space for the entire image doesn't work good (limits the gamut too much)
    1. Create a separate docker, which works like a palette, where the user can "paint" and mix the color he wants
    2. Connect the RYB color space to the paint device used in that docker (if people still like blending effect)
    3. If people don't like blending effect produced by RYB, search for some papers to implement the blending properly. In Krita 1.6 there was such a docker (was removed later), so the code can be searched there.
  1. Painterly color mixing

As discussed on IRC, this is not a good project idea.

X. Useful links

  1. Undo framework. Basically, we use Qt's undo framework. It is forked and named 'KUndo2Stack', but the general idea is exactly the same:
  1. Strokes Framework. Brief explanation how all the actions in Krita run: