A close look at the sRGB formula

The formulas for converting sRGB colors to linear, and the reverse, are usually given as follows:

sRGB to Linear
ConditionValue
0 ≤ S ≤ 0.04045L = S/12.92
0.04045 < S ≤ 1 L = ((S+0.055)/1.055)2.4
Linear to sRGB
ConditionValue
0 ≤ L ≤ 0.0031308S = L×12.92
0.0031308 < L ≤ 1 S = 1.055×L1/2.4 − 0.055

The definition uses two different functions – a straight line and an exponential curve – glued together at a certain “cutoff point”. The implication is that these functions (the ones in the sRGB to Linear definition) intersect at the point:

(0.0404500000000000, 0.00313080000000000)

If we take a close look at the function, though, we can see this intersection point is not exact, so the formula has a slight discontinuity:

sRGBLinear
0.0404500000000000 0.00313080495356037
0.0404500000000001 0.00313080728306769

If we extend the functions, we see that they actually intersect at two points:

The intersection points are approximately:

(0.0381547987133173, 0.00295315779514840)
(0.0404482362771082, 0.00313066844250063)

If we use either of these two points as the cutoff point, there will be no discontinuity at all. It’s apparent that the sRGB inventors selected the second of these points, and rounded its value to 4 significant digits to get 0.04045. They then used that rounded sRGB value to recalculate the Linear value, and got 0.00313080. I don’t know why their Linear value has more significant digits (5 or 6) than their sRGB value (4).

I guess that if you’re a perfectionist, and want no discontinuity at all, you can tweak the formulas like this:

sRGB to Linear
ConditionValue
0 ≤ S ≤ 0.0404482362771082L = S/12.92
0.0404482362771082 < S ≤ 1 L = ((S+0.055)/1.055)2.4
Linear to sRGB
ConditionValue
0 ≤ L ≤ 0.00313066844250063S = L×12.92
0.00313066844250063 < L ≤ 1 S = 1.055×L1/2.4 − 0.055

It doesn’t make any practical difference. The two functions are extremely close together in this region, so the precise cutoff point is almost irrelevant.

0.03928?

Some references give a formula with a different cutoff point:

sRGB to Linear
ConditionValue
0 ≤ S ≤ 0.03928S/12.92
0.03928 < S ≤ 1((S+0.055)/1.055)2.4

Evidently, this came from the fact that the slope of 1/12.92 is actually a rounded version of a more theoretically correct slope of about 1/12.92321. A cutoff of 0.03928 is what you would arrive at if you used that slope.

However, the sRGB standard defines 12.92 as the exact value to use. So I don’t think it would be correct to use 12.92321 in sRGB formulas.

In any case, there’s certainly no reason to use 0.03928 together with 12.92. That would be half-baked, and it leads to a discontinuity that is possibly big enough to be significant:

sRGBLinear
0.0392800000000000 0.00304024767801858
0.0392800000000001 0.00303949248622587