Draft: Refactor our blendmodes to properly support HDR modes
This is a rather big patchset that refactors our blendmodes to properly work in floating point and (especially) HDR color spaces. Previosly, a blendmode could easily generate negative or HDR values when the user didn't expect that. In the worst case, the result could even become NaN. All these cases are tested in the unittest now and continuously verified.
The patch splits the blendmode by their behavior related to SDR-preservation and positive-preservation. A blendmode can preserve both, one or none. See the definitions below
SDR-preservation
A blendmode is...
-
SDR-preserving (stable) --- if source and destination values are SDR (i.e. belong to the range 0.0...1.0), then the result is guaranteed to be SDR (i.e. in the range 0.0...1.0). The "stable" part means that if a small numeric error appears and the source and/or destination values, and they slightly drop outside the SDR range (i.e. -1e-6 or 1.00000001), then the result will not increase this error. Stable modes mean that even with small numerical errors the result will stay near 0.0 and 1.0 points.
-
SDR-preserving (unstable) --- strict SDR-range is preserved, but in the presence of small numerical errors bringing input values outside the SDR range the result can move far away from 0.0 and 1.0 values.
-
SDR-non-preserving --- inpuit values belonging to SDR range can easily bring the color outside the SDR range. E.g. Addition or Substract modes
Positive-preservation
A blendmode is...
-
Positive-preserving (stable) --- if any input value in the range [0.0...+inf] cannot make the result negative. The "stable" means that small negative values (i.e. -1e-6) will not bring the result far from 0.0 point
-
Positive-preserving (unstable) --- same as above, but the small negative input values can make the resutl "very negative"
-
Positive-non-preserving --- positive values can make the result negative, e.g. Substract blendmode.
What it means for a normal user
If a blendmode in sdr-preserving, then the user can convert an image from int16 to float16/32 space, and all the blending modes will continue to work in exactly the same way. That might be especially important for layer styles that use non-standard blendmodes.