This is an old revision of the document!
Brightness
In the simplest terms the “brightness” of a pixel is its luminosity value as perceived by a human eye (making infrared and gamma rays \(0\) “bright”). There are quite a few competing standards and definitions of what the means exactly, but for our purposes we will use the \(L\) component of the HSL color space as our “brightness” value of a pixel.
Again, in the simplest terms, increasing or reducing pixel's brightness can be interpreted as adding or subtracting a fixed “gain” value (others may argue that a more natural approach would be to use a multiplier, while others still may bring the “vibrancy” approach into picture).
In RGB color space
In RGB color space the operation is a matrix multiplication of the RGB's vector by a given “brightness” matrix. However we should make sure that the relative proportion of color channels is preserved so that the colors are not washed out.
Considering that the luminance is calculated as (see luminance)
\[lum = 0.2126 * R + 0.7152 * G + 0.0722 * B\]
Further consider that the brightness is simply a “boost” to RGB components, or in other words: gains. And as such all that is needed is to add the brightness \(br\) proportionally to each channel:
\[ \begin{bmatrix} R \\ G \\ B \end{bmatrix} + \begin{bmatrix} 0.2126 * br \\ 0.7152 * br \\ 0.0722 * br \end{bmatrix} \]
Of course when implemented on FPGA the preference is to use integer arithmetic, which can be easily achieved by multiplying the “inconvenient” floating point numbers by \(1024\):
\[ \frac{ \begin{bmatrix} R \\ G \\ B \end{bmatrix} \times 1024 + \begin{bmatrix} 871 * br \\ 2929 * br \\ 297 * br \end{bmatrix}}{1024} \]
N.B. In the above calculations the range for \(R, G, B\) values is \([0..1.0]\), so keep that in mind when using a different scale.
In HSL color space
When using the HSL color space the adjustment is as simple as elementary school's arithmetic operation. Namely - just a simple addition.
With that the implementation of the Brightness adjustment can be as simple as the following (where the “luma”, or brightness component \(\in[0..100]%%\)):
// pseudo-code void brightness(/*array of pixels*/image, int _br){ for(const & pixel: image){ pixel.luma = std::clamp(pixel.luma + _br, 0, 100); } }