Introducing "primaries" feature for sigmoid

Introducing sigmoid’s “primaries” feature

There’s a new feature of darktable’s sigmoid module in master. The initial work was done in this pull request where you can read all the relevant technical details. I thought it might be good to provide a more hands-on introduction at this point.

However, some brief background information must be given first.

The current code in master is a soft launch of sorts - none of the default settings are changed at this point, and your existing workflow, be it sigmoid or filmic, works just as before.

I’m keen to see results that people get with this feature. Please take a moment to read through the below information to get the most out of it.


The purpose of this new feature is to improve the existing picture formation provided by the sigmoid module.

In particular, the point is to address difficult light conditions such as presented in this Play Raw by Egocentrix and also give a better rendering of the yellow-orange range. Think of skin tones, sunsets, sunflowers etc. where the current defaults give a “salmon-like” hue at times. It has been discussed on this forum widely previously.

Overall, the ultimate goal is to give a reasonable starting point for edits and improve the robustness of the image formation process.


The process capitalizes on the per-channel curves mode of the sigmoid module. An S-shaped curve is applied separately to each of the RGB channels.

Now, you might know this distorts the ratios of the RGB values in various ways. The first thing is that the hue is shifted. The other effect is changes in saturation, increasing the saturation in the shadows and decreasing it the highlights. Especially the latter is usually desirable as it provides a smooth path to white.

These effects depend on the set of working primaries used, as well as the shape of the curve. Previously sigmoid always used the working primaries that were specified in the input profile module (usually Rec.2020). The new feature allows these to be changed. This has surprisingly profound effects as will be described in this post.

Notice that while the controls look very similar to the new rgb primaries module, this feature in sigmoid is a whole different process and can’t be replicated by just adding a rgb primaries instance before sigmoid. Sigmoid takes care of restoring the insets and rotations after the per-channel curve process, so that the middle range values, which are largely unaffected by the per-channel curves, return to their original places. The consequence is that the settings have the most prominent effect on the highlights but leave the middle range largely untouched.

New controls

While I want to emphasize that the smooth preset is the one you should use as a starting point, it is useful to get familiar with what the controls do.

These can be found under the primaries section.

  1. base primaries: chooses the set of primaries that are used as the starting point for the adjustments in this section. This sort of allows to override the working profile locally. This is necessary to be able to create presets where the results don’t change even if user switches the pipeline working profile.

  2. Red, green and blue attenuation: decrease the purity of the red, green and blue primaries before the signal is processed through the per-channel curves. An important consequence is that now even the brightest and most pure inputs get smoothly degraded to achromatic at the high end.

It is best to visualize the effect with a gradient sweep. The following visualizations are done with this gradient image by Troy Sobotka. It is interpreted as linear Rec.709 (same primaries as sRGB) at the input. base primaries in sigmoid is set to sRGB for demonstration purposes.

Image with default settings but hue preservation disabled. Notice how the values get stuck when they go higher, and eventually degrade to the pure primary and secondary colors, known as “the Notorious Six”. This is problematic as the picture doesn’t convey the increasing brightness at all!

Same settings but all attenuation sliders as 10 %. Notice how the high end got a lot better already.

  1. Red, green and blue rotation: rotate the primaries where the per-channel curves are applied. This affects the hue paths when approaching white in the high end. This is, again, best to visualize using a real image.

Compared to the previous one, slight rotations have been applied to all the primaries. Notice how this effectively counters the Abney effect in the blue stripe. Also, a small rotation of red to make the reds converge to yellow rather than magenta.

Notice that rotating one of the primaries also rotates the opposing secondary color (e.g. blue → yellow), which will be seen in the high end where the colors converge to the secondaries.

  1. Recover purity: value 100 causes all of the attenuations to be restored after the per-channel process is done. This lands the middle range values near their original purities. Value 0 doesn’t restore the purity at all, so the more you apply attenuation, the less purity there is in the final picture. Notice that the rotations are always restored regardless of the value of this slider.

The reason for not always restoring the original purity is that the per-channel process also causes an increase of purity in some parts of the image. This may lead to values that are outside of the output medium range, and those values are clipped at the output. This leads in posterization, which can make the image look pretty broken.

As above but recover purity set to zero.

Just to showcase the effect of these adjustments, a pair of lightsaber images with the initial and final settings from this section.


“smooth” preset

A new preset called smooth is introduced to provide a reasonable starting point for your experiments. It aims to give a similar contrast as the current defaults but changes other aspects of the rendering, giving an opinionated look. As the name suggests, smoothness is the main goal of the settings. Some reasoning behind the values:

  • skew = -0.2: provide the highlights with a bit more breathing room, allowing for smoother transitions there and slower change of hue towards the secondaries.

  • hue preservation = 0: as you have already seen in the above section, the process relies on the peculiarities of the per-channel curves. The attenuation of purity brings the hue skewing to a reasonable level already. Additionally, some of that hue skewing seems to be actually preferred, seen from examples where things like sunsets or sunflowers show a “salmon-like” color when the hue preservation is at 100 %. You can experiment with this.

  • base primaries = Rec2020: most users have Rec2020 as their working profile, and that’s what sigmoid defaults use as well. When making a new preset, it is important to choose something else than the work profile option, as that would cause the preset look to shift randomly when the user changes their working profile in input color profile module.

  • attenuations and rotations: they have been tuned somewhat according to a similar process as described above. Essentially eyeballing for a reasonable result. If you have an image with e.g. difficult blue LED lighting, grab the blue attenuation slider and increase the value as needed.

  • recover purity = 0: to avoid posterization issues at output. As the per-channel process already saturates the shadow range of values, it might be not good to risk posterization by increasing the purity afterwards. Increase this as needed but observe posterization when doing so.

Alternative settings for sRGB output

If you work to solely export to sRGB, you might consider setting the base primaries to sRGB, along with settings like this:

The choice of sRGB base primaries, combined with recover purity = 0, ensures that the output is within the sRGB gamut. This may help avoid posterization.


Problem with sunset colors by Nicolas Winspeare (CC-BY-SA)

Just applied the smooth preset and adjusted exposure. Notice the gentle path towards the sun that approaches yellow but lacks all the harshness.

A study in blue by Egocentrix (CC-BY-SA)

Applied smooth preset, adjusted exposure and blue attenuation. Delightfully good result with ease.

[Play Raw] Tree leaves under a “very nasty” blue LED lighting by Daniel Faucon (CC-BY-SA)

Here I started with the smooth preset but had to push the blue attenuation slider quite a lot to get rid of posterization in the background. This is where a smooth gamut compression method could come in handy. It’s an area that would deserve some love in the future. Also, this is probably the toughest image with blue LEDs that I’ve encountered during testing.

More examples pictures in the pull request.


Not a color grading tool

Pushing the rotation sliders too much, you might end up with truly broken images. This should not be considered as a creative or a color grading tool. There’s little wiggle room to the sliders before the image gets really funny.

I even thought about just making “canned” presets that would have reasonable rotations in place already, with no option to adjust, but in the end went with the sliders because I thought it’s a good thing to leave the option to tune things.

Just don’t get too excited about pushing those sliders, but rather aim at a good looking image. Ideally, you should be able to pretty much stick with a constant preset and do fine color adjustments elsewhere.

Clipping and posterization

Sigmoid doesn’t include any control of output gamut. Therefore any values outside the limits of the medium are clipped at the output medium (display), leading to ugly transitions between colors, lost contrast / punchiness etc.

When seeking punchiness, it is important to consider the gradients in the image. If you push things so far that the gradients disapper due to clipping, the picture might lose part of its impact even if the saturation seems to be increased.

Which one of these has the greater impact?

(Image from this thread by ilia3101, CC-BY-SA)

Module order

As the process is based on attenuating the purity before the per-channel curves, it is not advisable to artificially increase the purity of the signal in any way before the sigmoid instance. This includes purity-increasing adjustments in color calibration and rgb primaries, as well as saturation boosts in color balance rgb. Consider any purity-increasing operations after sigmoid even if the default module position is before it.


The new feature was based on the original idea of Troy Sobotka, coined AgX, and related discussions with the wonderful people over at the Blender Artists forums.


Thanks for the excellent write-up.

I’ll need to re-read it to make I’ve “got it” but it’s already answered most of my unspoken questions.

Might sound funny to some but this is the kind of thing that makes me proud to be a darktable user!

Thanks for your work!


Can we make this a blog post?

1 Like

Its soooo frustrating that we keep getting tools that have me wanting to re-edit every image I’ve made. Like come on I need to be finished editing at some point :dizzy_face:


Thanks for the great post, and great work! The smooth preset is really good in my (still limited) tests. The reason why I asked how it was derived (and also the reason why I was afraid that the answer was “eyeballing”) is that unfortunately it seems to break relatively easily with changes to the tone curve. For example, trying to get less crushed highlights by changing the shape of the tone curve has led to subtle but unpleasant changes in the rendering in my experiments, especially in the low-saturation red-yellow region (i.e. “Caucasian skin tones”). These are hard to pinpoint, but clearly visible. I will try to play with the settings to see if there’s a way to counter this, but if you have comments or suggestions they are more than welcome!

1 Like

Hey, thanks for the input! Would be great to see some examples of this (if you can’t share the images, screenshots of the settings or a XMP file can also be a start).

The shape of the curve certainly has an effect on the rate of change toward white. It is kind of inherent to the per-channel curve mechanic. And we are very sensitive to spot if something is wrong with this rate-of-change, especially when it comes to skin tones.

This is precisely the reason why I didn’t make the choice of primaries a ”canned” immutable thing. If anything, they would have to be canned along with the curve parameters.

There is be work to be done to provide a more versatile set of presets.

This is a really informative post. I tested you ideas on a few images and it all makes sense. Most impressive was a stage shot taken under red spot lights. Your primary adjustments helped bring out so much detail. I look forward to the new user guide that includes this. While I am not knocking filmic, sigmoid is much more user friendly and a great addition to the DT tools

I hear you!

However I am profoundly grateful for the chance to “have another go” at some images. Moreover, as our toolkit keeps improving in number and quality of tools, and (hopefully) increasing competence in using them, some results that seemed nigh impossible in years gone by now seem possible.

This is why, especially for captures that cannot be repeated, I keep my RAWS and occasionally go back and “have another go”.

(BTW - I took you rant at face value; maybe I should have assumed it was tongue-in-cheek, and you were praising the evolution of our toolset).


I’d rather wait until the next release (4.8?) or so, so that ideally we could even establish a set of sensible presets for people to use, and most of the pitfalls would have been already found so that solid advice on efficient usage can be given.

Assuming this is tongue-in-cheek. :slightly_smiling_face: On a more serious note, you might not find this making a major difference on many of the photos, but certainly worth trying on some shots you had difficulties with, if you’re interested.

Oh, and please feel free to discuss in this thread, post your findings, processed pictures, questions etc.


Yes. :partying_face: thank you for your work! I’ve taken up photographing neon signs with a bloom filter. Usually I’m religious about not clipping, but the bloom filter looses it effect with bracketing, so there is some amount of clipping. This and the primaries module seem quite useful in that respect.


Thanks for your contribution @flannelhead ! Really nice to see this coming along so well :slight_smile:



that might be. Nevertheless, here’s one example that I can share (and please forgive the questionable model). The first xmp is with the “smooth” preset of sigmoid at default settings. In the second, I changed the curve slightly, to have brighter highlights without affecting (ideally, at least) the look of the main subject. Notice however how the skin tones have changed. As I wrote in my previous post, the change is subtle, but it’s definitely noticeable to me, and it feels “off” (though I’m not sure I would notice if I didn’t have the other version to compare to). I should also add that I did try to play with the primaries to correct the wrong feeling, but failed: no matter what I tried, I couldn’t get a result I was happy with. Maybe it’s just the wrong curve, but maybe you can still find this useful…
IMGP0833-smooth.xmp (6.6 KB)
IMGP0833-tweaked.xmp (6.6 KB)
IMGP0833.dng (19.1 MB)

1 Like

Thank you too - for going through the hard work of creating the module, and also for the good discussions we had regarding this feature.

It think there are still things to be improved, but it is kind of good that this sort of improvements can be made and shipped incrementally, in small parts.


Thanks, going to look at that when I get the chance :slight_smile:

I was curious and tried your sidecars at work… just heading home but curious… I am on 4.5 +877 so a bit behind … but loading your sidecars produced black images and the settings in sigmoid were all weird …almost zero for contrast… 0 for white and black… anyway dashing now but will try on something I built last night at home later…

Hmmm, I have no idea what is going on, sorry. I’m not familiar with dt’s sidecars, the only thing I can say is that I pulled from master a couple of days ago I believe

Sorry, was having trouble getting the right xmp. @agriggio, Alberto, how does this look? No major tweaks other that using “smooth” in sigmoid.

IMGP0833.dng.xmp (7.4 KB)

IMGP0833.dng (19.1 MB)

1 Like

Fine with the newer version at home… 4.5 + 1218…

1 Like

Seems like mostly very small change in red??




thanks for your efforts, but maybe I should clarify: this is not a play raw, it’s a feedback report :slight_smile:
I welcome discussions about how the primaries interact with the tone curve (such as “recipes” or general hints about how the primaries should be tuned according to the curve parameters, what degree of “correction” to expect, what other modules/settings should or should not be used, and so on), but I think that more generic “apply this preset and it will look good” or “here’s my take” are less interesting in this specific context.