## Converting between sRGB and linear values

The sRGB color space used for example in 8 bit images has to deal with the nonlinear brightness perception of human vision. It does this via a nonlinear mapping between the binary brighness value and the actually displayed brightness. It basically is a modified form of gamma encoding with a gamma value of approximately 2.2.

In order to add two images by actual brightness we need to convert the sRGB brightness values of the raw image data into linear brightness values, add them and then convert them back into sRGB values in order to display them on monitor devices [1].

The wikipedia page on sRGB [2] directly gives the two formulas for converting from sRGB value $C_{\rm{sRGB}}$ to linear value $C_{\rm{linear}}$ as

$$C_{\rm{linear}} = \begin{cases} C_{\rm{cRGB}} / 12.92 & \text{when} & C_{\rm{cRGB}} \le 0.04045 \\ \left( \frac{ C_{\rm{sRGB}} + 0.055 } {1.055} \right) ^{{2.4}} & \text{when} & C_{\rm{cRGB}} \gt 0.04045 \\ \end{cases}$$

and back as

$$C_{\rm{sRGB}} = \begin{cases} 12.92 \cdot C_{\rm{linear}} & \text{when} & C_{\rm{linear}} \le 0.0031308 \\ 1.055 \cdot C_{\rm{linear}}^{{1}/{2.4}} - 0.055 & \text{when} & C_{\rm{linear}} \gt 0.0031308 \\ \end{cases}$$

which we can write as JavaScript function

function sRGB_to_linear( C_sRGB )
{
if( C_sRGB <= 0.04045 )
{
C_linear = C_sRGB / 12.92;
}
else
{
C_linear = Math.pow( (C_sRGB + 0.055) / 1.055, 2.4 );
}

return C_linear;
}


and

function linear_to_sRGB( C_linear )
{
if( C_linear <= 0.0031308 )
{
C_sRGB = C_linear * 12.92;
}
else
{
C_sRGB = 1.055 * Math.pow( C_linear, 1/2.4 ) - 0.055;
}

return C_sRGB;
}


.

Now we can use these functions to add the brightness values of two images as

brightness1 = ...get one from image RGB values
brightness2 = ...get one from image RGB values

brightness_sum =
linear_to_sRGB(
sRGB_to_linear( brightness1 )
+
sRGB_to_linear( brightness2 )
);


and get a proper sum of the brightnesses.