Project

General

Profile

General concept about masks in darktable

PRINCIPLES:

  • I A mask limits the effect of an iop.
  • II Every iop can only have one mask.
  • III The mask of an iop can be constructed using multiple "mask generators".
  • IV Masks are reusable.
  • V Masks should be powerful enough for elaborated tasks but need definitely be simple to use. simplicity is more important than some extreme advanced use cases.

DEFINITIONS:

  • A "mask" is used to blend the result of the current iop with the input layer (the output of the preceding iop). Normal blending for example results in a mask ranging from 0..1.0 depending on the opacity slider.
  • A "mask generator" is a function which defines the masks. The blendif modifier is a mask generator in this definition, because the input/output slider define which areas of the mask created with blendif are opaque, and which are not. Other possible mask generators could be closed splines, or even a drawing engine which allows to draw the mask onto the image.

DERIVED PRINCIPLES:

  • a) I --> some iops may not have masks (demosaic, ...) but most should support them
  • b) III, IV --> there needs to be a single module in darkroom mode that allows management of masks and mask generators.
  • c) IV --> all modules that support a mask need a way to give the user access to the mask and the mask generators.
  • d) IV --> the mask management module (b) has to allow to export and import masks. Not the masks are stored, only the parameters of the mask generators.
  • e) IV --> there has to be a way to share masks between images without going through the file system (d). this must however not clutter the masks module in other images.
  • f) V --> there needs to be a way to combine multiple "simple" mask generators into one composited masks (donut shapes, spline+blendif, ...).
  • g) V --> editing masks has to be done on the canvas, or in one of the panels.
  • h) V --> the user interface to do (g) has to follow established principles used in other software to aid the user.

DETAILS:

  1. The mask itself (the bitmap) is not stored in the db, only the parameters of the mask generators
  2. Masks are used as soon as the blend mode of an iop is not "off".
  3. The mask manager module should be the central point to work with masks.
  4. The blendif mask generator is special in one way: splines get created by the user and can have arbitrary forms, the blendif settings depend on the actual pixel data of a module. therefore a masks derived from splines can easily be reused while the reusing of a mask created with blendif need special consideration from the user. It has to be clear that a mask generated from blendif can be copied to another iop, but only the mask is reused, not the blendif generator.
  5. Since masks are living outside of the modules the masks manager has to be located in the left panel of the darkroom.
  6. Working with masks includes creating masks, editing masks, (re-) naming masks, duplicating masks, importing masks, linking masks, exporting masks and combining multiple mask generators or masks into new compound masks.
  7. The mask module also needs to make it easy to see a list of all masks of the image, to identify the masks and relating mask generators and possibly to filter masks (used/unused, linked ...).
  8. Linked masks and masks generators allow multiple iops to share the exact same mask and mask generators, editing the mask in one iop is also changing all linked instances.
  9. Every module that allows mask usage can have either no or exactly one mask assigned at any point in time.
  10. The GUI should be as simple as possible while being as informative as possible. It should be enough to add a single dropdown field which contains all current masks and mask generators -- including mask generators of mask groups, possibly in tree form -- and an entry for "no mask". If a mask is used, the field could read "2 shapes + blendif" for example, maybe a better solution can be found.
  11. The usage of masks may not limit the usage of blending, both methods to influence the result of a module have to be usable at the same time in a single module.
  12. When duplicating mask generator groups, the whole stack of elements has to be duplicated.
  13. When editing a mask on canvas, only the edited mask is to be shown. however, when editing mask generator groups, all elements of the group have to be shown, but only the controls of the currently edited mask generator.
  14. In order to be able to create complex masks from simple mask generators the mask generators have to be able to punch holes into other masks. Either by explicitly setting mask modes for mask generators in groups or by other means. This together with groups allows to combine masks using boolean operations.
  15. Masks have to support feathering. the falloff has to be controllable. for circles a single value for the whole mask might be enough, for curve mask generators this has to be configurable individually for different parts of the mask (one way would be to have the setting per node).
  16. Possible types for vector mask generators include circles and freeform masks. the latter have to support both curved line segments as well as straight borders, and both cups nodes as well as round nodes. fancy forms like stars are not needed, may however be provided as predefined shapes.
  17. In the future there should be support for a "draw masks" generator. It should not store the bitmap mask but vectorize the strokes. The way to do that should be a curve for the center of the stroke together with the width of the stroke, adjustable at every position of the line (similar to the falloff). Pressure readings from the input device should be used for the stroke width and/or falloff when possible.
  18. It should be possible to bake mask groups into a single mask, provided the implementation allows it.
  19. It might be worthwhile to use svg syntax to store paths (at least for export/import) so that they can be used in external programs like inkscape. Care has to be taken however to correctly import masks that come from an external application and that contain features we don't support in our user interface.
  20. In general masks have to be transformation aware (they have to cover the same part of the image before and after lens correction). however there should be a way to make masks "static" for when they don't follow image features but have a meaning of their own (for example letters or a logo). this should be exposed in the masks manager with a toggle able lock icon or something similar.

Streamlining the UI for masks

Currently all drawn mask types (circle, brush, etc.) use some kind of key+mouse wheel combination to change the attributes of that mask. To streamline the UI for the upcoming 1.4 release, which is the first "public" release with masks, the combination should be standardized if possible.

Current Situation

Circle
  1. ctrl + scroll to adjust the opacity
  2. scroll inside of form to adjust the total size
  3. scroll inside of the feather area of form to adjust the size of the feather
  4. right click on form to deleted the mask
Ellipse
  1. ctrl + scroll to adjust the opacity
  2. ctrl + click&drag in vicinity of form to adjust the orientation
  3. click & drag on node to adjust the eccentricity
  4. scroll inside of form to adjust the total size
  5. scroll inside of the feather area of form to adjust the size of the feather
  6. right click on form to deleted the mask
Polygon
  1. ctrl + scroll to adjust the opacity
  2. scroll inside of form to adjust the total size
  3. scroll inside of the feather area of form to adjust the size of the feather
  4. click & drag on node of the main form to adjust the position of the node
  5. click & drag on node of the feather form to adjust the width of the feather at the selected node
  6. click & drag on segment to adjust the position of the segment
  7. click & drag on handle of selected node to adjust the curvature of the node
  8. ctrl + scroll to adjust the opacity
  9. ctrl + click on segment to add a new node
  10. ctrl + click on node to toggle between sharp corner or bezier corner
  11. right click on node to deleted this node
  12. right click on segment to deleted the mask
Gradient
  1. ctrl + scroll to adjust the opacity
  2. scroll in the vicinity of one line (either middle line or feather line) to adjust the feather width
  3. click & drag on handle to adjust the rotation of the gradient
  4. click & drag in the vicinity of one of the lines to adjust the position of the mask
  5. right click in the vicinity of one line (either middle line or feather line) to deleted the mask
Brush
  1. ctrl + scroll to adjust the opacity
    Before painting:
  2. scroll to adjust the total size
  3. shift + scroll to adjust the ratio solid <-> feather area
    After painting:
  4. scroll inside of the feather area of mask (more in vicinity of the feather line) to adjust the size of the feather
  5. scroll inside of the feather area of mask (in vicinity of the main line) to adjust the ratio solid <-> feather area
  6. right click in the vicinity of one line (either middle line or feather line) to deleted the mask
  7. click & drag on node of the main form to adjust the position of the node
  8. click & drag on segment to adjust the position of the segment
  9. click & drag on handle of selected node to adjust the curvature of the node
  10. ctrl + click on segment to add a new node
  11. right click on node to deleted this node
  12. right click in the vicinity of one line (either middle line or feather line) to deleted the mask

Problem

As listed above, the usage of the key + mouse combinations differ from mask to mask. This can irritate new users and will lead to a lot of questions to which the answer is always "rtfm". This could be avoided if the UI can be standardized.

First proposal for changes:

Use the same control scheme for as much mask types (and similar iops maybe):
  1. ctrl + scroll to adjust the opacity - Already implemented for all mask types
  2. Always use simple scroll for the size adjustment of the form and only for the complete form (which means dotted line for brush mask) - The decision which element to resize by hovering near one of the elements can be quite frustrating especially for the polygon mask and the brush mask.
  3. Always use shift + scroll for the adjustment of the feather area or ratio solid <-> feather - This simplifies the work and solves the problem above that sometimes the right selection of an element (form or feather area) by hovering is difficult for some masks.
  4. Always use shift + click & drag to adjust the orientation of a form - Advantage: the handles of the gradient mask can be eliminated. This could also be used for other iops like the GND.
  5. Similar to ctrl + click to add a node in a segment, use ctrl + right click to delete a node - it often happens that the whole form is deleted if you don't hit the node you wish to delete.
  6. Merge circle and ellipse - use ctrl + click on node to set eccentricity like a circle and use shift + click & drag to adjust the rotation - Advantage: One icon less.
  7. Add in changing mouse icons - For example pointer with "+" sign if ctrl is pressed and hovering over a segment where a node can be added. Or a pointer with a rotation symbol if the form can be rotated if ctrl is pressed.

It may be useful to copy some general behavior from the darktable ui to masks:
For example shift + double click to reset the feather area or ratio solid <-> feather area

Situation after proposal

Circle - merged with ellipse
Ellipse - including circle
  1. ctrl + scroll to adjust the opacity
  2. shift + click & drag in vicinity of form to adjust the orientation
  3. click & drag on node to adjust the eccentricity
  4. ctrl + click on node to reset the eccentricity to "circle"
  5. scroll inside of form to adjust the total size
  6. shift + scroll inside of form to adjust the size of the feather
  7. right click on form to deleted the mask
Polygon
  1. ctrl + scroll to adjust the opacity
  2. scroll inside of form to adjust the total size
  3. shift + scroll inside of the feather area of form to adjust the size of the feather
  4. click & drag on node of the main form to adjust the position of the node
  5. click & drag on node of the feather form to adjust the width of the feather at the selected node
  6. click & drag on segment to adjust the position of the segment
  7. click & drag on handle of selected node to adjust the curvature of the node
  8. ctrl + scroll to adjust the opacity
  9. ctrl + click on segment to add a new node
  10. ctrl + click on node to toggle between sharp corner or bezier corner
  11. ctrl + right click on node to deleted this node
  12. right click on segment to deleted the mask
Gradient
  1. ctrl + scroll to adjust the opacity
  2. scroll or shift + scroll in the vicinity of one line (either middle line or feather line) to adjust the feather width - One could argue that the "size" of the gradient is indeed the feather area
  3. shift + click & drag to adjust the rotation of the gradient
  4. click & drag in the vicinity of one of the lines to adjust the position of the mask
  5. right click in the vicinity of one line (either middle line or feather line) to deleted the mask
Brush
  1. ctrl + scroll to adjust the opacity
    Before painting:
  2. scroll to adjust the total size
  3. shift + scroll to adjust the ratio solid <-> feather area
    After painting:
  4. scroll inside of the feather area of mask to adjust the size of the feather
  5. shift + scroll inside of the feather area of mask to adjust the ratio solid <-> feather area
  6. right click in the vicinity of one line (either middle line or feather line) to deleted the mask
  7. click & drag on node of the main form to adjust the position of the node
  8. click & drag on segment to adjust the position of the segment
  9. click & drag on handle of selected node to adjust the curvature of the node
  10. ctrl + click on segment to add a new node
  11. ctrl + right click on node to deleted this node
  12. right click in the vicinity of one line (either middle line or feather line) to deleted the mask

Also available in: PDF HTML TXT