# Applying Photoshop's "Shadow / Highlight" Correction Using Standard Image Processing Algorithms

Adobe's Photoshop has an excelent filter called "Shadow/Highlight" used to correct, in one step, dark areas AND overexposed areas of a photo. By simple analysis, I suppose it uses some radius-dependent adaptive contrast algorithm (halo effect is typical), possibly combined with interpolation (even extra-dark or extra/white, clipped areas get very improved with this filter.

The parameters used can be seen in the dialog box below What I would be looking for is a way to start exclusively with the parameter values given in the dialog box, apply a sequence of parameterized operations "blindly", and get back the result non-interactively (well, perhaps previewing the image while adjusting parameter sliders in some GUI environment).

Any suggestion about how to perform this with standard, well-known image-processing algorithms?

I think this can be achieved through histogram stretching. Input pixel values (levels) are mapped using linear transform from $<\textbf{min}_{in},\textbf{max}_{in}>$ to $<\textbf{min}_{out},\textbf{max}_{out}>$. The intensity transform for input and output pixel values look like this:

$$I_{out}=\frac{I_{in}-\textbf{min}_{in}}{\textbf{max}_{in}-\textbf{min}_{in}}\cdot(\textbf{max}_{out}-\textbf{min}_{out})+\textbf{min}_{out}$$

The formula can be simpler, but this one is more clear, at is transform input values from one interval to the other.

By default, $\textbf{min}$ is 0 and $\textbf{max}$ is 255 (depending on bit depth). Increasing value of $\textbf{min}_{in}$ emphasizes shadows, while decreasing $\textbf{max}$ emphasizes lights.

There are also "radius" track bars, so I suppose the histogram operation can be done adaptively / locally, i.e. histogram is computed for a window at every pixel instead of whole image.

Gaussian blur on work image prior to histogram computation may be convenient when the window is small to avoid sharp transitions.

Similarly, you can compute difference map which you smooth and then apply.

The adjustment will likely disturb color balance, so applying to luma channel only or computing adjustment of gray value and applying to R,G and B channels should suffice.

• Interesting thoughts, although I already suspected that such concepts were being used. Have you already used this Photoshop filter? It is totally impossible to get its great result by any simple combination of levels (first three paragraphs of your answer) and other filters. Sep 19 '12 at 15:51
• Maybe it is something more like a custom generated curve and the processing is done in Lab, hence treating the highlights and shadows perceptually in the same way for every color. Sep 19 '12 at 17:29
• One way to decode this would be to perform the filter on sample images and then comparing their histograms or response curves pixel by pixel. Sep 19 '12 at 17:30
• You can apply different mappings to different regions of the same histogram. For example, you could stretch the input range of 0-10% intensity to the output range of 0-25%, 10-90% --> 25-75% and 90-100% to 75-100%. This is a crude example; the mapping curve can be made smoother than this. I have implemented (in an FPGA for video processing) a full histogram-flattening algorithm that "spreads out" any peaks in the histogram wherever they might be. The result looks a little unnatural, but it sure brings out the detail in low-contrast areas, which is key for applications like video surveillance. Sep 21 '12 at 15:38

This Mathematica code substitutes a "gamma" operation for whatever Photoshop's "Amount" parameter controls, but it achieves roughly the same result.

Manipulate[
Module[{
i1 = GaussianFilter[Binarize[img, {0, t1}], r1],
i2 = GaussianFilter[Binarize[img, {1 - t2, 1}], r2]},
(i1*img^g1 + img*(1 - i1))/2 + (i2*img^g2 + img*(1 - i2))/2
],
{{t1, 0.2, "Shadow Tonal Width"}, 0, 1},
{{g1, 0.75, "Shadow Gamma"}, 0.1, 2.5},