User Tools

This is an old revision of the document!


Contrast

Increasing the contrast increases the separation between dark and bright, making shadows darker and highlights brighter. Increasing it too much may clip both limits' values. Decreasing the contrast brings the shadows up and highlights down to make them closer to one another.

Essentially when the contrast is increased, the pixel's \(L\) value gets “pushed away” from the center of the values' scale, and when the contrast is decreased the \(L\) is being “pushed towards” the center.

In RGB color space

As with the brightness adjusting contrast in RGB color space requires us to pay attention to proportionally adjust the individual color components of the pixel to preserve their relative ratios.

Traditionally the luminance is calculated as (see luminance)

\[ lum = 0.2126 * R + 0.7152 * G + 0.0722 * B \]

With that in mind each component's contrast adjustment is based on its luma's weight \(k\) and the adjustment itself is calculated as

\[ component = (component - 50*k) * contrast^2 + 50*k \\ luma \in [0..100] \\ contrast \in ]0..2.0]%% \]

which looks like this:

\[ \begin{bmatrix} R - 50 * 0.2126 \\ G - 50 * 0.7152 \\ B - 50 * 0.0722 \end{bmatrix} \times contrast^2 + \begin{bmatrix} 50 * 0.2126 \\ 50 * 0.7152 \\ 50 * 0.0722 \end{bmatrix} \]

which easily simplifies to

\[ \begin{bmatrix} R - 10.63 \\ G - 35.76 \\ B - 3.61 \end{bmatrix} \times contrast^2 + \begin{bmatrix} 10.63 \\ 35.76 \\ 3.61 \end{bmatrix} \]

Of course, much like in brightness case, we'd like to not use floating point arithmetic:

\[ \frac{ \left(\begin{bmatrix} R \\ G \\ B \end{bmatrix} \times 1024 - \begin{bmatrix} 10885 \\ 36618 \\ 3697 \end{bmatrix} \right) \times contrast^2 + \begin{bmatrix} 10885 \\ 36618 \\ 3697 \end{bmatrix} }{1024} \]

In HSL color space

For our purposes we are going to adjust the pixel's \(L\) component in the HSL color space, leaving the other two components intact as the Saturation shouldn't be affected by the Contrast and the Hue (at least for now) is also maintaining its invariance during this operation.

Assuming the \(L\) component to be in range \([0..100]%%\) the contrast adjustment looks like this: \[ luma = (luma - 50) * contrast^2 + 50 \\ luma \in [0..100] \\ contrast \in ]0..2.0]%% \]

// pseudo-code
void contrast(/*array of pixels*/image, double _cst){
  for(auto & pixel: image){
    pixel.luma = std::clamp((pixel.luma - 50) * _sct * _sct + 50, 0, 100);
  }
}

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information