Why
One of darktable’s strength is undeniably its super powerful and flexible masking system. However, there are some hardcoded limitations in the current system (in terms of mental model, UX and capabilities) that, to me, always felt arbitrary and introducing unnecessary friction. Among the main pain points:
- Disjoint mental models apply to shapes, parametric and raster masks
- The hard to understand include/exclude and positive/negative polarity used to combine drawn and parametric masks
- Parametric channels can only be intersected, whereas shapes can be combined with different operators (e.g., union, exclusion, etc.)
- Only one parametric mask (albeit multi-channel) per module
- Raster masks cannot be combined with anything else, it’s take it or leave it, which greatly limits their usefulness
- A UI divided between a module’s mask panel and the mask editor, which sits all the way across the screen and uses a different mental model (set operators instead of “exclude/include - positive/negative” as in the main panel)
So, over the course of the last weeks I started working on a proposal to refactor how masking works and move past all these limitations.
The result
Behold the Flexi mask panel (this is an awful working name, but for the time being it will do):
What this is
-
A working implementation of a proposal to revamp the mask editing UX in darktable around two guiding principles:
- A simplified mental model, in which all mask elements are mask elements (be them parametric channels, shapes or raster masks) and can be combined using the same set of operators
- A focused UI where all mask-related functionality lives in one place, as opposed to being split between a module’s mask panel and the mask editor.
-
A personal endeavour, which at the moment of writing has no buy in from @Pascal_Obry or the dev team. In fact, no one knows that I was working on it.
-
A way to collect feedback from the community (and the devs) on a concrete proposal and a working prototype instead of just handwaving and daydreaming.
NOTE: While this is a very early prototype, I have done countless iterations on it. I have tried hundreds of different configurations and tried many different solutions. What I propose here is not just a “quick and dirty sketch” of a feature. It is the result of a lot of thought and experimentation. This is not to say that there is no margin for improvement, but rather to stress the fact that the choices that I made concerning the underlying model and the UI are based on thoughtful considerations and experimentation.
What this is not
- A preview of a PR ready for review
- An assertive statement about how masking should be done
- A polished, finished product with no gaps and all bugs squashed out: everything more or less works, but
- the code is defnitely not production quality and
- I didn’t spend too much time trying to make it efficient
- Something that has already been discussed with @Pascal_Obry and the rest of the dev team and that got some kind of green light from them (I know that I said that already before but I think it cannot be stressed enough)
Documentation
Overview of the Flexi panel
In a nutshell:
- Parametric channels, raster masks and shapes are all mask elements.
- Mask elements are arranged in groups, which are composed from the bottom up, like the pipe.
- You can have as many groups as you like, and as many elements (of any type) as you like inside each group. So you can have a group where you combine a raster mask with shapes and parametric channels, and you can have multiple such groups in each mask.
- You can apply refinements at the element, group and whole-mask level.
- Within each group, elements are unordered and they are combined with a single within-group operator: union, intersection or screen (i.e., soft union, to smooth out feather overlaps).
- Each group is composed with the previous group using a between-groups operator (i.e., all the set ops already available in the mask editor, plus “screen” and “multiply”).
- You can drag and drop groups and shapes to rearrange stuff.
- You can create group-presets to store and reuse group layouts that you plan to use frequently (only the groups and their ops are saved, not the mask elements).
- The clicks-per-mask ratio is not higher than the classic panel for simple masks, and I would argue that it is much lower for more complex ones.
This README file explains in more detail how the Flexi panel is different from the classic one:
Demo
In this short demo video, I am desaturating the high saturation blue and orange, to demonstrate a union of parametric channels:
User docs
For the brave people who want to try this out
Builds
Check the Releases page of my darktable fork, and download the latest release tagged with masks_revamp, e.g.:
My ask to the community
Ok, this is the most important thing of the whole post, so I left it for last.
I would like if as many people as possible could give it a try, and let me know what they think. I don’t care so much about the fine details (i.e., I do not like this icon, or this icon should go there instead) as much about the mental model, the functionalities and the main UX abstractions:
- Is the new mental model simpler and easier to understand?
- What are the main wins and losses of this new proposal?
- What do you like and would like to use?
- What do you think that is not necessary and could be done without?
In all cases, please factor in your habits and biases, and try to judge it objectively. We all (including myself) are certainly more proficient with the “classic” mask panel, because of muscle memory and because we trained ourselves extensively with it.
What do I expect from this exercise
Not sure. It will depend on the response of the community, and especially that of the devs. If there is an agreement that it’s by and large a direction that we want to pursue, then we have a good starting point that we can start refining iteratively. If there are some clear NOs and DONTs or we find that the proposal lacks in some obvious way, then I am happy to iterate on it until we reach some kind of consensus and then try to get this merged. We can also decide that we do NOT want anything like this, which is also a totally plausible final state.
Thanks for reading this long post, looking forward to your feedback!
P.S.: A special shoot out to @Terry, with whom I had discussed my intention to do something along these lines a few months ago, @martinus who was asking for better group support a couple of days ago, @s7habo because I would really love his feedback and @Thad_E_Ginathom who is keeping an eye on my work on masks ![]()
P.P.S.: Please, let’s keep this discussion focused and grounded on technical considerations. There is a lot to unpack and if we start branching out in unrelated directions it’s going to become very messy very soon.







