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.
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.
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.
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.
- 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.
- 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.
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.
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.
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.
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)
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.