| Index: src/core/SkSRGB.h
|
| diff --git a/src/core/SkSRGB.h b/src/core/SkSRGB.h
|
| index 08ba860e4a5df9aeb545d95165a62b37dc969728..31fd4aec5e2d31f005121fc03caddb491ce385b0 100644
|
| --- a/src/core/SkSRGB.h
|
| +++ b/src/core/SkSRGB.h
|
| @@ -28,14 +28,15 @@ static inline Sk4f sk_clamp_0_255(const Sk4f& x) {
|
| return Sk4f::Min(Sk4f::Max(x, 0.0f), 255.0f);
|
| }
|
|
|
| -static inline Sk4i sk_linear_to_srgb(const Sk4f& x) {
|
| +// This should probably only be called from sk_linear_to_srgb() or sk_linear_to_srgb_noclamp().
|
| +// It generally doesn't make sense to work with sRGB floats.
|
| +static inline Sk4f sk_linear_to_srgb_needs_trunc(const Sk4f& x) {
|
| // Approximation of the sRGB gamma curve (within 1 when scaled to 8-bit pixels).
|
| //
|
| - // Tuned by brute force to minimize the number of bytes that fail to round trip,
|
| - // here 0 (of 256), and then to minimize the number of points halfway between bytes
|
| - // (in linear space) that fail to hit the right byte, here 131 (of 255), and to
|
| - // minimize the number of monotonicity regressions over the range [0,1], here 0.
|
| -
|
| + // Constants tuned by brute force to minimize (in order of importance) after truncation:
|
| + // 1) the number of bytes that fail to round trip (0 of 256);
|
| + // 2) the number of points in [FLT_MIN, 1.0f] that are non-monotonic (0 of ~1 billion);
|
| + // 3) the number of points halfway between bytes that hit the wrong byte (131 of 255).
|
| auto rsqrt = x.rsqrt(),
|
| sqrt = rsqrt.invert(),
|
| ftrt = rsqrt.rsqrt();
|
| @@ -45,8 +46,20 @@ static inline Sk4i sk_linear_to_srgb(const Sk4f& x) {
|
| auto hi = (-0.0974983f * 255.0f)
|
| + (+0.687999f * 255.0f) * sqrt
|
| + (+0.412999f * 255.0f) * ftrt;
|
| + return (x < 0.0048f).thenElse(lo, hi);
|
| +}
|
| +
|
| +static inline Sk4i sk_linear_to_srgb(const Sk4f& x) {
|
| + Sk4f f = sk_linear_to_srgb_needs_trunc(x);
|
| + return SkNx_cast<int>(sk_clamp_0_255(f));
|
| +}
|
|
|
| - return SkNx_cast<int>(sk_clamp_0_255((x < 0.0048f).thenElse(lo, hi)));
|
| +static inline Sk4i sk_linear_to_srgb_noclamp(const Sk4f& x) {
|
| + Sk4f f = sk_linear_to_srgb_needs_trunc(x);
|
| + for (int i = 0; i < 4; i++) {
|
| + SkASSERTF(0.0f <= f[i] && f[i] < 256.0f, "f[%d] was %g, outside [0,256)\n", i, f[i]);
|
| + }
|
| + return SkNx_cast<int>(f);
|
| }
|
|
|
| #endif//SkSRGB_DEFINED
|
|
|