What to try
- Move Encoded channel C and compare the measured linear value with both ramps.
- Choose Near black and move through the C = 0.04045 breakpoint.
What to look for: C = 0.5 decodes to about 0.214. Near black, sRGB uses a linear segment; equal stored-value steps and equal light steps produce different ramps.
How it works
For an encoded channel C between zero and one, values up to 0.04045 decode as C / 12.92. Larger values decode as ((C + 0.055) / 1.055)^2.4. This piecewise definition is more precise than treating sRGB as a single power of 2.2.
Linear-light values are needed for meaningful exposure changes and relative-luminance calculations. An encoded midpoint of 0.5 decodes to about 0.214, not 0.5. Arithmetic in the two domains consequently produces different blends and gradients.
Use it in the Lab
The Lab’s Exposure tool converts to linear light before applying stops. Its general Gamma adjustment is a creative tone control and is a different operation from decoding a known transfer function.
Limits & distinctions
Do not apply sRGB decoding twice to already-linear data. A photograph’s appearance also depends on capture processing and display conditions beyond this one transfer curve.
Further reading
The RGB values stored in digital images are not a linear representation of light intensity. They are gamma-encoded — compressed through a power curve — to match the non-linear sensitivity of human vision and to make more efficient use of limited bit depth. Before performing any mathematically correct color operation, you must reverse this encoding through gamma expansion.
Why Gamma Exists
Human vision is more sensitive to differences in dark tones than bright tones. Gamma encoding allocates more of the available bit range to darker values, where our eyes can tell the difference. An 8-bit channel storing linear light would show visible banding in shadows; gamma-encoded, it distributes those 256 steps more evenly across our perception.
The sRGB Transfer Function
The standard sRGB gamma curve is not a simple power function. It has a linear segment near zero and a power segment for the rest:
function srgbToLinear(c: number): number {
// c is 0–1 (sRGB encoded)
return c <= 0.04045
? c / 12.92
: Math.pow((c + 0.055) / 1.055, 2.4)
}
function linearToSrgb(c: number): number {
// c is 0–1 (linear light)
return c <= 0.0031308
? c * 12.92
: 1.055 * Math.pow(c, 1 / 2.4) - 0.055
}Impact on Distance Calculations
If you calculate Euclidean distance directly on gamma-encoded values, dark color differences are exaggerated and bright color differences are compressed. A distance of 10 between two dark grays will look much more significant than a distance of 10 between two light yellows. Linearizing first ensures that equal distances correspond to equal physical differences in light energy.
Common Pitfall
Averaging two sRGB colors by simply adding and dividing by 2 produces a result that is too dark. This is because sRGB addition is not linear — you must linearize, average, then re-encode. This applies to any blending, interpolation, or distance calculation.
When You Can Skip It
For palette extraction via color grouping (as used in our Studio tools), the goal is perceptual similarity rather than physical accuracy. In this case, working directly in sRGB and using a generous distance threshold is often sufficient and much faster. The physical error is acceptable because the grouping threshold already absorbs it.
Related Lab categories
Sources & references
Guide updated
