PhotoFlow - new dynamic range compressor tool (experimental)

I have started to work on a dynamic range compression tool that, in combination with the existing film-like tone mapping curves, seem to give a quite natural rendering of HDR images.

The algorithm is based on this paper and the provided sample code, while the bilateral blur filter is derived from Darktable.

The idea is rather simple:

  • compute the log-luminance of the image (linear RGB input data is required)
  • apply a bilateral blur to the log-luminance, and extract the high-frequency component
  • apply a linear contrast reduction to the blurred log-luminance
  • add back the high-frequency details
  • undo the log encoding
  • blend the new luminance with the original image colors

Here is an example using this HDR file from RT (@Morgan_Hardwood I hope there is no problem if I use this file as an example… I guess you might be also interested in the results I get) :


For reference, here is the starting point:


The new code has been committed into the stable branch. That’s how the new tool looks like:


The output of the dynamic range compressor is still linear HDR RGB data, which can be further manipulated. For example, I find that applying a film-like tone mapping curve on top of the dynamic compression (like in this specific example) allows to nicely recover the global contrast that is lost in the compression.

Feedback is highly appreciated as usual. Also, if you have any HDR image you would like to share and use to test this tool, please go ahead and submit!


I tried it yesterday. The operations are sensible and processing fast. I like it!

If you could explain what each parameter does for the forum, even better. :wink:

Sure! The inial post was just an appetizer… :wink:

Have you compared it to darktable’s exposure fusion in the basecurve module?

In Darktable, the same kind of algorithm is used by the tone mapping module, however they seem to use a different implementation of the bilateral filter for this module, and the resulting image shows some artefacts:


Maybe @houz has some ideas?

The exposure fusion module AFAIK is based on laplacian pyramids. It does a really good job, except for the brightest highlights:


The version from today should be faster… let me if you manage to test it as well.

Hmm maybe more something for @hanatos

Wow… very impressive :ear_of_rice:& powerfull :sheep:!!! Congrats =) :penguin::point_left:

Try to see what happens when reducing the edge threshold…

I am getting this when at fit zoom level.


… :eye: orgazm … drop drop :droplet: :cricket::turkey::droplet: :+1::dog::poultry_leg::jack_o_lantern::dash::bath::mauritania::burrito::exploding_head::exploding_head::exploding_head::exploding_head::exploding_head::exploding_head::exploding_head::exploding_head::exploding_head:

@afre you should feed PhF only organic :candy: everybody and their donkey knows that’s an lsd sideffect :–P

1 Like



What settings are you using?

I have added separate adjustments for shadows and highlights to the dynamic range compression tool.

At this point, this new tool is a valid replacement of the existing shadows/highlights tool, which I will then remove from the UI (but will still remain in the code, and be available when opening old PFI files that made use of it).

Here is a brief explanation of the filter parameters:

  • shadows/highlights strength: how much compression to introduce (0 gives the input image)
    the filter preserves mid-gray, so whatever the value of the S/H strengths, a 50% gray patch will not be modified
  • local contrast: amount of local contrast that is re-introduced in the image.
    The local contrast is computed as log(L) - blurred(log(L))
    A value of 0 means “all local contrast is added back”,
    -1 means “no local contrast” - equivalent to the filter applied directly to log(L),
    +1 means “local contrast is added back twice”
  • coarseness: radius of the underlying bilateral blur, expressed as a fraction of the image dimensions. Too small values can introduce visible halos.
  • edge threshold: value variance of the bilateral filter. For higher values the filter will be less effective on textures (i.e. textures are preserved and not compressed)

@Carmelo_DrRaw no problem, and great result!
How about this one?


here is what I could achieve with a quick edit (dynamic compression + film-like tone mapping curve):



I also did a quick test with the tractor image (dynamic compression only):



The main limitation for the moment is speed at large coarseness values, but I have some ideas how to improve this…

What do you think?

Looks very good!

@Carmelo_DrRaw, perhaps you could try this pic of a samba band (well half, the other half are rather hidden). I had to use a fairly extreme curve to get it passable, and it shows! The raw is here -

00518-Sambistas-crowd.jpg.out.pp3 (10.7 KB)
Keep up the great work!

Default settings using the current version of PhotoFlow.


Here is what I get with my usual combination of dynamic compression and film-like curve:

I had to work on a scaled-down TIFF file, because the current code is still too slow to process such big images. Anyhow, here is the corresponding PFI file: 00518.pfi (10.5 KB)
If you want to use it, you first need to process and export your RAW image into a 32f TIFF file in linear REC.2020 colorspace; I have used the 4k preset for the TIFF size.

I think that the shadows recovery looks quite natural… what do you think?

Here is a screenshot of the settings I have used:


1 Like

Indeed, the default settings are rather aggressive, especially on images like this one that do not need very strong adjustments:

Lowering the shadows/highlights strength gives some more natural result: