What is the Implementation of a Low, Mid or High Tone Dodge or Burn in GIMP? In The GIMP, and also in photoshop, you have the DODGE/BURN tool to enhance colors in shaded or highlighted regions, which would otherwise be blackish or whiteish. I found empirically that this filter is a good preprocessing step for a computer vision task I am implementing.

I found here that there are 6 formulas which simply map RGB values to other RGB values independently of channel or pixel location. According to the link the transformation is y=x+0.25*sin(x) for midtone dodging.

However, I could not verify this with the gimp source code, an excerpt from gimpoperationdodgemode.c:



gboolean
gimp_operation_dodge_mode_process_pixels (gfloat              *in,
                                      gfloat              *layer,
                                      gfloat              *mask,
                                      gfloat              *out,
                                      gfloat               opacity,
                                      glong                samples,
                                      const GeglRectangle *roi,
                                      gint                 level)
{
  const gboolean has_mask = mask != NULL;

  while (samples--)
    {
      gfloat comp_alpha, new_alpha;

      comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity;
      if (has_mask)
    comp_alpha *= *mask;

      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;

      if (comp_alpha &amp;&amp; new_alpha)
    {
      gint   b;
      gfloat ratio = comp_alpha / new_alpha;

      for (b = RED; b &lt; ALPHA; b++)
        {
          gfloat comp = in[b] / (1.0 - layer[b]);
          comp = MIN (comp, 1.0);

          out[b] = comp * ratio + in[b] * (1.0 - ratio);
        }
    }
      else
    {
      gint b;

      for (b = RED; b &lt; ALPHA; b++)
        {
          out[b] = in[b];
        }
    }

      out[ALPHA] = in[ALPHA];

      in    += 4;
      layer += 4;
      out   += 4;

      if (has_mask)
    mask++;
    }

  return TRUE;
}


The essence of the code would boil down to these two lines. The other code is for handling transparency of the brush and iterating over pixels and color channels.



gfloat comp = in[b] / (1.0 - layer[b]);
comp = MIN (comp, 1.0);


Suggesting a general formula for all tones and both burn and dodge of  y = x / (1- f(x)). I could not trace the value of layer[b] back to anything sensible, and hence do not know what f(x) is supposed to be.

Moreover, the Wikipedia page on dodge and burn, and general pages about tone mapping, only mention the principle, but not any formulas.

Are there different definitions of dodge and burn filters? What is the definition, in the form of a formula y=g(x), of the gimp tool?
It basically using what Photographers calls "Shadow Mask" / "Highlight Mask".

If the image is in the range [0, 1] "Highlight Mask" is actually the value of the pixel.
"Shadow Mask" is the inverse, namely 1 - Highlight Mask.

Use this mask as linear interpolator of the result with the originals.