Introducing the filmic module in darktable

I like to see such discussion, as I think a lot of our mis-communication about raw processing gets confused when we’re considering different starting points.

Me, I think of it “soup-to-nuts”, from opening the raw file to saving the JPEG or whatever. In that, there are a couple of milestones:

  • demosaic
  • first non-linear transform

For the first one, the fundamental organization of the image data changes from the bayer or xtrans pattern to RGB pixels. Some things can be done either side of that, others not so much.

Then, the first tone transform from the original light energy measurements takes the image toward perceptual sweetness and away from its real existence in nature. And we’ve learned of recent that you shouldn’t do that too early in the pipeline…

All the other ordering considerations are situational and discretionary. And, one might decide to do a sub-optimal order if their priorities or inclinations drive them that way. We’d just want to go into them with eyes open to the implications…


Any picture needs preparation for display, which implies anchoring scene middle grey to display middle grey, then compress or decompress white and black around that middle grey value.

EV, aka log2(luminance).

The transform converts linear to display-referred without the display gamma. The output of filmic can’t be called linear. That’s why opposing gamma-encoded to linear doesn’t make sense and is misleading in many ways.

I prefer to say scene-referred or scene-linear for everything directly representing the light emission with no non-uniform scaling. Then you are display-referred once you have applied a view transform to anchor grey/white/black in your display space (filmic or OpenColorIO are view transforms). That view transform may or may not take into account the Opto-Electrico-Transfer-Function encoding (which can be a simple gamma or any fancy HDR encoding), which is not needed as long as you are working in a floating point pipeline, but only when you convert to unsigned integers (8-16 bits).

You are right. Except filmic doesn’t necessarily reduce contrast, it just blindly remaps given the bounds you input. That can result in increase or reduction of contrast, your call. It’s just a mapping.

Once you have properly anchored white, black and grey with filmic, the black point compensation of your color management system should take care of the actual dynamic range of the output for you. Technically, that could be adapted in the display settings of filmic too, but the pipe is not ready for that, so we need to deal with it later.


Ok, it is more clear now to me.

So the curve is logarithmic (EV in horizontal axis) and is adapting the input to an output that is more similar to how human perceive lightness.
That is why it seems linear in the midtones (inside latitude) but really it is not.
It does not represent output versus input (as in most curve manipulating programs), but versus log2 input.
May be it is easy to make it user selectable (I have discovered you can change it in base curve) and so you can have the typical output versus input curve.

At the same time it is compressing the extremes (outside latitude) to fit it in an output DR (which one, our display profile, export profile, print profile? there are many selected at the same time).
I think it is a bit confusing and what causes most of our misunderstandings.

Which is the profile that filmic is using and the DR it is considering when you work in the screen tab?

OK, I understand that you are not mapping to the output device, a linear mapping is done in the final step in the output profile (or conversion to display) transformation.

We can think of filmic as having a virtual output device (or just transforming to the 0.0 to 1.0 output).

But still, it does the compression outside the latitude to compress lights and shadows.
But the quantity of compression you need depends on the real DR of the output device related to input.

I there is enough DR in output to your DR in image, you do not need to compress anything, but if you change the device, to a less capable one, there you need to decide best way to compress it and what to preserve.

I have the impression that filmic is biting too much things at the same time: a transformation that make things more similar to human perception and a compression that fits the DR to an output DR.
It would be easier to understand (and select what you want to do and what you don’t) to do that in two steps.

It does a great job with images that have a wide DR and you want to display them in a standard sRGB monitor with 8 EV, for example.

But what happens if you have a display with 10 EVs?
And if you want yo print it in a printer with lower DR and quite different colors?

I suppose you should change parameters in filmic to adapt the output to that printer.
And that is one of the problems I anticipate with making two works at the same time.

You may have applied some processing after filmic, because that processing is better done in a space more close to human perception (vignetting in perceptual uniform way, for example or changes in colors or saturation).

If it were separate steps, with a last step for mapping just before output profile you have to change nothing if you change the output media, but tweak that last compression step.

The other kind of images where I don’t see clearly how to work in a linear + filmic workflow is with images that have say 4 o 5 EV in origin, filmic still is useful to adjust contrast and have an output similar to human perception.
But it keeps trying to compress the range in the extremes when there is no need for that, as a pure logarithmic transform would fit perfectly our input range in the output range.

In that situation many times you don’t want to compress the DR, but to expand it.

But (as long as I know) you cannot get rid completely of the curved zones in the extremes using filmic.

If I have enough dynamic range in my output device to show the DR of the imagen, I don’t need any compression of lights or shadows, and if I apply filmic there is always some.
You can minimize it, but it is still there.

And if you change the output device, for one with larger or narrower DR you have to change filmic curve in order to fully exploit the dynamic range of the output device wihout unnecessry loosing or desaturating colors

If the process were split in to phases, you just need to change the final step of comprising DR, and the contrast and gray point may be adjusted in a previous curve to get the logarithmic / perceptual related output.

1 Like

Filmic is a tone mapping operator like reinhard or drago, it’s mainly function is to compress highlights above 1 to 1 in a linear working space.

I think it’s the best choice for raw editing because it add a nice s-shaped curve.

Looking how a base curve is shaped, it’s clear that all base curves are effectively exposure + highlights roll off + contrast in the shadows.
For this reason the filmic module could be used for low DR raw too, and with good results.
However i see this is more like a convenient “hack”.

@anon41087856 It could be a nice idea to use in the white level slider a more user-friendly misure like nits or simply the max value in linear floating point.

I agree, it gets great results doing that when your main interest is the midtones and your lights are not clipped (when they are may be you have to fix that first, I have not done many tests about that).

But it is presented as a general purpose substitution of the more traditional aproach of applying curves or the base curve and to substitute the step of conversion to log space where you can apply effects in color lab for example.

Even in the case you apply it for tone mapping, you have to adjust the latitude when the DR of the output changes in order to get the most of the output.

May be that if you have 8 steps of DR output you dedicate 2 steps to compress zones and lights softly, and have 4 steps of lattitude (in the output).

But if your output has 12 would you dedicate 3 steps to shadows and light transitions or keep 2 steps of transition and have 8 EV of latitude instead 6?

If you readjust latitude, then every processing after filmic should be retouched, I think.

When I apply it to low DR images, it does still a great general job, but lights seem to be a bit washed out an get a bit dull not very bright. I think it is due to compression of lights, even if I try to keep lattitude to de maximun and adjust white point to be as close to burn lights as I can.

May be I am not very good with the sliders in filmic and don’t find the appropiate combination.

I can provide some example if you want (in other thread in order to keep this in focus).

1 Like

Not really, is presented with other modules like the color balance and tone equalizer to do editing in a linear and unclipped working space.

After these early steps is possible to use curves or other modules.
It’s possible to start with curves or base curve too.

The could be due to the desaturation of the module itself.
In my opinion there’s no reason to use filmic for a ldr image, but it’s necessary if was used some other module that push the values above 1 (like the contrast slider in the basic module, or exposure,…)

A log space is used in the filmic module, you are referring to gamma encoded space

I’m not sure to understand this, but you want to use a tone mapping function if there are values above 1.

Well that was not my impression reading some of the articles of aurelien or watching his videos.
He provides solid arguments against using traditional base curve or using the RGB curves we are used to in photo editing.

He teaches us how to adjust black, gray and white level and does not seem to be talking just about High DR images.

But that is exactly what I am trying to dig in, if this is just for images where the dinamic range significantly greater than your output device or it applies as a general procedure to process every image in the final steps, in substitution of the base curve.

With light clipped images there seems to be issues (there always are).

Even with the intended purpose you are sacrifying details in lights and shadows in favor of midtones, which is usually the right thing to do, I suppose, and you can use lattitude to adjust how much.

As @anon41087856 presents it, you just make minor adjustments to exposure in order to get no clipped lights or out of bounds shadows, but do not apply processing (I mean luminosity adjustments) prior to filmic.

But with low DR images I am having issues.
Of course there is no clipping and I adjust the general light exposure to get a medium bright.
You have an overall dull image.

Then you apply filmic and adjust black and white (and gray) points, but I always finish with less detail in lights and shadows than using a more traditional approach (using levels for example and them some contrast).
You have great control of contrast and a good transition with filmic.

In this cases where the linear image is just a small part of the histogram you have a hard work adjusting or editing the image in the linear space.
Nothing works as expected, as if you use a curve lights are not where you expect it. Contrast does not make great difference or does strange things (depending on the position of histogram with respect to the mid gray)…
So using just filmic makes quite difficult to process the image prior to its use.

If I use a linear luminosity curve to expand the histogram in the first step after input profile (or levels) I get a more controlable image where lights and shadows are where you expect them.

It seems you can use filmic after that (expanding the dinamic range). But it always generates some light and shadows smoothing.

No, I don’t think so, gamma is applied only in the output profile step (if the output profile has a gamma).
Even processing with filmic there is the final output profile step.
I suppose that if the profile has a gamma it still applies it, doesn’t it?

The filmic module and the base curve are used to increase contrast in the image and give the output a response that is more similar to human perception, am I wrong?

That seems what aurelien says and differentiates that two steps in pipeline: the physical related part prior to filmic/base curve in the linear space and the perceptual part after filmic/base curve where things are not linear and you have a more perceptually appealing image.

In a perfect world, if our output devices could reproduce the light intensity and contrast that you can find in the real world, you would not need to abandone the physical related world, the linear pipe.
You could do editions and processing but if you don’t, the rendered final scene would be exactly the same as the original scene.

But with our limited devices, they cannot reproduce so much DR nor have a very bright light.
Eye adapts to it and works comparing relative light intensities from light to shadows (but not linearly but in its perceptual logarithmic way).

That it why we need to make adjustments with non linear curves to adapt the DR of the scene to the output and give the eye a similar impression of contrast and bright light (even when the monitor emits way less light intensity).

At least that is how a see it (please correct me if I am wrong).

If I understood @anon41087856 correctly, filmic does not work directly with the DR of the output.

It just takes a range of values 0 to 1 and outputs another one 0 to 1 but using a logarithmic transform.

Only inside lattitude part of the curve is logarithmic.
Outside lattitude the curve compresses the range to fit 0 and 1 in the extremes.

If I understood that correctly, through black and white points you fix which part from 0 to 0.xb you assign to black compression and which from 0.xw to 1.0 to light compression being lattitude from 0.xb to 0.xw.

Then the output profile maps that range from 0 to N EV being N the output profile DR.

So if you adjust 0.xb to be 0.25 and 0.xw to be 0.75 you get 4 EV of lattitude and 2 EV for black and white compression.

if your output has 12 EV and apply the same curve, you have 6 EV of lattitude and 3 EV of black and white compression (0,25=12).

Wouldn’t it be better to get 8 EV of lattitude and 2 EV of compression zones?
That would be what you would obtain if filmic works with absolute output DR, but it does not.

So to fix only 2 EV for the zone of compression you have to alter the parameter in order to get 0.1666 and 0.8333 as black and white points.

Where can I see the equations that filmic is using in the transformation?

1 Like

Please post a sample. A lot of my photos are in blue hour and thus have very low dynamic ranger. Filmic has been much easier than anything else.

1 Like

I will prepare one of them and upload it to a new thread, showing it with no curve, with filmic applied and processing it in my own.

But in my tests it seems that edition of this kind of pictures tends to be easier if you apply first leveles or a linear curve to expand the histogram and then adjust filmic parameters with a greater dinamic range, than using just filmic and adjust black and white points to stretch the range.

Yes you’re wrong, the filmic module it’s a tonemapping operator exactly like reinhard, his primary function is to compress highlights above 1 to 1.

The first step is the logarithmic shaper :

y=(log2 (x/gray) - black)/(white-black)

black and white are misured in EV
gray =0.18

The white EV is the white relative exposure slider in the filmic module and it rapresents how many stop above middle gray there are, aka the max value in the image (generally above 1) that will be mapped to 1.

Reading that value in EV you could do the conversion yourself and see what the is max value using this formula( is it correct @anon41087856?) :



The inverse formula if you know the max value is:


To me keeping the EV value in the white relative exposure just generates confusion

Thank you a lot .

I have been trying to put all that in an excel

I understand well the shaper function.

With the transfer function from the log output of the shaper to the output device

For an gray level of 0,18 in the camera input and -10 EV for black point and 2 EV for white point I get a the gray level output from shaper is 0,83333


Everything OK for that.

Problem comes with transfer function

I use 0.18 gray for display and gamma 1

So the gray level of the display is 0.18^1/gamma= 0.18

In appearance I use a 6 EV lattitude for display output son rel latt is 0.5

Calculation of Toe gives me
TL= 0,41666 which seem correct

But the output coordinate is
TD= -236666


The problem is the position of the graypoint.

If Gl is 0.8 and the gray level in output display is 0.18 then you trace a line with unity slope through that point you get negative number.

In filmic gray point of output seems to be much higher, but @anon41087856 says it is 0,18^1/gamma (0.18 in this case).

I can’t see what is wrong.

That is the display of the transform between the logarithmic output get from the shaper function to output display isn’t it?

You first transform your image data using shaper function and then you transform that with the transfer function to contrast the output and smooth the lights and blacks…

1 Like

It doesn’t compress only highlights above whatever level, it compresses everything above middle grey so the end of the curve hits 100% display-referred.

No, filmic takes values between whatever non-zero and whatever other non-zero, and pack that inside 0 and 100% display-referred. To do that, the middle grey values acts as a pivot/fulcrum/anchor. You need to forget about 0 and 1, those are not special numbers in the scene.

I don’t understand what you are trying to compute in the first place.

1 Like

Sorry for the delay, @anon41087856.

I am trying to understand what filmic curve does and how.
So I am trying to reproduce the calculations in excel (using the english version of the article in your web).

I believe I am having troubles with some concepts like the GrayPoint.
I had thought I knew what it was, but now I am not so sure.

I am confused, and my calculations do not have sense, so I am misunderstanding something.
Please help.

GrayPoint is define “everywhere” as the relative intensity of light that perceptually you see as a middle gray.

lets consider the shaper function alone

y= \frac{log_2(x/grey)- black_{EV}}{DR}

That implies that if you can appreciate say 12 EV ( DR= 12 ) being 0 the darkest point where you cannot distinguish any detail and 12 the lightest where you see no detail, middle gray would be 6EV, with 6EV range for shadows and 6 EV for lights (so black_{EV}=-6, white_{EV}=6)

I am assuming that the input that is coded in 12 bits (from 0 to 4096)

To calculate the input corresponding to a middle gray ouput, I take y=0,5 (a perceptual gray 6EV from the blackpoint).

if we calculate corresponding input:

x=gray \times 2^{ y \times DR+black_{EV}}
x_{gray}= 0.18 \times 2^0=0.18

we get 0.18 as expected.
If we calculate the camera value it would be X_{grey} = 4096*0.18= 737.28 \sim 737.
Lets calculate the corresponding camera value to black point (y=0)

x_{black}= grey \times 2^{black_{EV}}=0,18 \times 2^{-6} =2.8125 \: 10^{-3}

The corresponding camera value would be X_{black}= 4096 \times 2.8125\: 10^{-3}= 11.52 \sim 12
Now I will try to calculate the corresponding camera white point that I have expected to be 4096.

With this dynamic range of 12 EV, the white point is 12EV above the BP and 6EV over grey point, being y=1

x_{white}= 0.18 \times 2^{12-6}=0.18 \times 64=0.18 \times 64= 11.52

which is greater than one, if we calculate the correspoingi camera value it gives us X_{white}=47186.

Obviously I am misunderstanding something.
As equations are taken from your paper and I have revised calculations, it cannot be the calculations.

So I am misinterpreting grey point or white point.

May be grey point does not correspond to middle gray in output (y=0.5) but then, what does middle mean? Are wrong all that places that talk about it as the perceptual middel point?

Cameras do not punt middle gray in the middle of the distribution, canon has white_{EV}= 2.5 and a dynamic range of say 12 EV (so black_{EV}=-9.5}.
I had thought that was to let more room to shadows than lights.

May be it is the concept of white point as a number of EV in the output space.

I calculate the output corresponding to a camera value of 4096, I get:

X_{white}=4096 \rightarrow x_{white}= X_{white}/X{grey}= 4096 / 737.28= 5.55556

If I calculate the corresponding output value is:

y_{white}= \frac{log_2{\frac{5.5556}{0.18} +6 }}{12}= 0.91232

The pure white will be then in the 10.94 EV (just about 11 EV above black and not 12) so the DR won’t be 12 and the lights would have 4.94 EV and not six (but we made all calculations with a DR of 12 EV).
And the grey point won’t be in the middle of the perceptual output any more.

So what is the gray point and which is the corresponding perceptual output value?

I think the trick is in the definition of gray and white point.

1 Like

First thing I noticed is that you put the middle gray at the center of the dynamic range.

But middle gray is a perceptual notion, and does not have to be in the middle of the dynamic range. E.g. in a snow landscape under cloudy conditions: most of the shaded will be at higher luminosities than “middle gray”. Or take a black cat on a dark background…

Or an image of an interior with a window. Where do you want to have the accent:

  • on the interior: then your middle gray will be taken with respect to the interior
  • on the garden: then your middle gray will be taken with respect to e.g. the lawn…

In at least one of those two options, middle gray will certainly not be at the center of the dynamic range.


I’m sure I am misunderstanding middle gray, thank you.

I was always said that middle gray was what we see as a medium gray, in the middle of the transition from black to white.

So I assumed it corresponds to y=0.5 the middle zone from 0 to 10 EV (in Adams zone system), so transition from 4 to 5 zone.

Is it the opposite? The middle of the linear light intensity where light intensity is halve the maximum?

Does that correspond to y=0,18 and zone 1,8 EV near the 2 nd zone?

I have observed too that in current cameras, white point is put somewhere from 2 EV to 2,5 EV from the gray point.
You can measure that seeing how much you can overexpose an image of a uniform iluminated surface before you clip lights.

So if we have 12 EV of dynamic range that would let you 2,5 EV for lights and 9,5 EV for shadows (BP= -9,5 EV).

So it is clear that it is not in the middle of anything.

But what is then grey point?

What is the meaning of 18% gray point?
That does mean that in a camera with a 12 bit sensor (4096 possible values) and if gray is 18% the gray value would be 0.18*4096= 737?

Yes, in a gamma encoded color space (rgb or Lab).
0.18^(1/2.4) =~ 0.5
In linear rgb middle gray is 0.18

This is true if you expose the photo so that a middle gray card is mapped to 0.18 (exposing for gray)

log2(0.18 * 4095)= 9 EV
log(4095/(0.18 * 4095))/log(2)=2.5 EV

If you underexpose by 1 stop (exposing for the highlights)
0.18 becomes 0.09

log2(0.09 * 4095)= 8.5 EV
log(4095/(0.09 * 4095))/log(2)=3.45 EV

In this last case in darktable is possible to add Digital exposure compensation so middle gray is ancored at 0.18 and the max value is 2.
Then use the filmic module.

1 Like

We are mixing up the middle gray from the displayed image and middle gray from the raw data.

First, in the final image, middle gray is at 50% luminosity, i.e. in the middle of the display range. I think we both agree on that. And of course, middle gray will always, by definition, be at the center of the dynamic range for a display-referred image (screen, paper, projector, …)

Now, let’s switch to the scene and the captured data.
The image you capture is exposed to make sure that none of the important zones in the image is clipped (clipped point highlights can be very difficult to avoid).

To transform that image from linear, scene-referred data to logarithmic, display-referred, we use the filmic module. That module has basically three parameters that influence the dynamic range that is covered:

  • middle gray luminance
  • white point
  • black point.

Now, there are several ways to set those values.
One way is to set the middle gray luminance where you want in (at 18.45% in filmic), then use the exposure module to get your middle gray where you want it, and in the filmic module, adjust white and black point to avoid clipping at either end of your luminosity range.
That will virtually always put your middle gray away from the center of the ev range. That is to be expected in the scene-referred data.

But the key point is that scene middle gray is where I decide to put it. Highlights and shadows will just have to adapt, and will end up somewhere, hopefully within my display range.
Again, I decide where middle gray is within the dynamic range covered by my input, not the math. And in general I decide to put middle gray at 18.45%. But I can very well put it at say 5%, or 25%. But that point that I set is the luminosity that will end up as middle gray in my output image
(cf. the filmic presets: middle gray luminance varies between 0.58% and 18.45%…)

In practice, you will use the exposure module (black point) to get your scene-referred values in a somewhat symmetrical range around your center, to avoid problems with the filmic shaper function. But that’s already a matter of taste, and not a requirement of the math.


I might be missing something but why would that be the case? If you are talking about signal levels, then it assumes both that the output space follows perceptual lightness and that white is 100%. But Report ITU-R BT.2408-3 (page 5) places HDR reference white at 203 cd/m², which is encoded in PQ (which is display-referred) as 58 % of the maximum signal value, and 18 % grey is placed at 26 cd/m² or 38 % signal, which is neither half of the maximum signal value nor half of the white signal value. (And also not 18 % of 203 cd/m², not sure what’s up with that…)

If you are talking about log units of dynamic range, then I also don’t see a reason why the output should have exactly as much headroom below middle grey as it does above.

Could you perhaps clarify what you mean? (Or what definition it is that makes it true by definition?)

OK, let me make some numbers.
Now it is more clear.

For now I am just talking about the camera raw values (X) and the normalize (0 to 1) values (x) and the output of the shaper (y) that translate them to the perceptual space.

Yes if gray is 18% Gray point is 2.47 EV bellow White ( x_{gray}= 0.18 x_{white} \rightarrow y_{white}= -log_{2}(0.18)= 2.47 EV over gray point).
Your arre right the middle gray is not in the middle of the output luminosity range, despite its name (silly me).

And that is more or less what canon camera sets, as you blow up the point where you are measuring when you overexpose something less than 2.5 EV.

We will suppose 12 bit camera (0-4096 numbers).
And a White point near the extreme, say 4090, and will suppose a 18% grey point.
We will suppose a black point in the camera taken data of 5 where the noise is so huge you discern nothing.

Let me calculate the corresponding values.

So at camera X_{white}= 4090, X_{black}= 4.

To normalize the values we us the white point set in the camera (4090) so input values will be normalize from 0 to 1

\\ x_{black}= 4/4090=9.78 \, 10^{-4}\\ x_{white}= 4090/4090= 1

Lets calculate the camera value of the gray point, as it is 18% of white point it should be:
X_{grey}= 0.18 X{white}= 0.18 \times 4090= 736.2

Let us calculate EV from white to grey point and from black to grey point:

White_{EV} = log_{2}(X_{white}/X_{grey})= log_2(4090/736.2)= 2.474 EV

As expected, and now BlackEV:

Black_{EV}= log_2(X_{black}/X_{grey}= log_2(4/736.2)= -7,524 EV

Much bigger than white, as it uses to be in the examples of filmic.

DR= White_{EV}-Black_{EV}= log_2(X_{white}/X_{black})= log_2(4090/4)= 9.998 EV

Roughly 10 EV as one would expect.

Lets calculate the shaper output:

\\ y= \frac{log_2(x/x_{grey})-Black_{EV}}{DR}\\ G_{log}=y_{grey}= -Black_{EV}/DR= 0.7526\\ y_{black}= \frac{log_2(9.78 \, 10^{-4}/0.18)+7,524}{9.998}=0\\ y_{white}= \frac{log_2(1/0.18)+7,524}{9.998}=1\\

So the shaper output goes from 0 corresponding to the black point value in camera to 1 corresponding to white point.

You only get negative outputs if your raw camera is less than the black point (4) and greater than one if 1 if the raw value goes above the stablished white point (4090).

If you use EV instead, it goes from 0 to DR (about 10) being grey point at -Black_{EV}

Is this OK for now?

Gray point is not at the middle of the logarithmic interval.


Well I had the same idea at first than him.

Everybody tells you that grey value corresponds to a 50% gray.

But in the logarithmic output of the shaper function it does not, in cameras it is at 18% of clipping level, I beleive and that is 2.47 EV from pure clipping white.

If your camera has 10 EV it is clear that you have more space bellow grey than above.

May be that when you transfer it to the output screen with a 2,2 gamma it ends in 50%.

I have not met that point yet, I wanto to be sure I understood correctly what shaper does and the meaning of white poing, black point and grey point (it is obvious I had not them as clear as I had thought).