| Index: src/core/SkColorSpaceXform.cpp
|
| diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp
|
| index 599adc90f959609062c6d9955ec01b0560428321..12c3801e47567b7a7125b46c2a9deb25da2094e8 100644
|
| --- a/src/core/SkColorSpaceXform.cpp
|
| +++ b/src/core/SkColorSpaceXform.cpp
|
| @@ -1329,6 +1329,173 @@ const
|
| }
|
| }
|
|
|
| +static inline Sk4f srgb_to_linear(const Sk4f& x) {
|
| + // Approximation of the sRGB gamma curve (within 1 when scaled to 8-bit pixels).
|
| + // For 0.00000f <= x < 0.00349f, 12.92 * x
|
| + // For 0.00349f <= x <= 1.00000f, 0.679*(x.^0.5) + 0.423*x.^(0.25) - 0.101
|
| + // Note that 0.00349 was selected because it is a point where both functions produce the
|
| + // same pixel value when rounded.
|
| + auto y = (x + 0.055f) * (1.0f / 1.055f);
|
| + auto twodotfive = y * y * y.rsqrt().invert();
|
| + auto lo = ((1.0f / 12.92f)) * x;
|
| + auto hi = twodotfive;
|
| + auto out = (x < 0.04045f).thenElse(lo, hi);
|
| + return out;
|
| +}
|
| +
|
| +template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM>
|
| +void SkColorSpaceXform_Base<kSrc, kDst, kCSM>
|
| +::applyYUV(void* dst, const uint8_t* srcY, const uint8_t* srcU, const uint8_t* srcV, int len)
|
| +const
|
| +{
|
| + Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT;
|
| + load_matrix(fSrcToDst, rXgXbX, rYgYbY, rZgZbZ, rTgTbT);
|
| +
|
| + if (len >= 4) {
|
| + // Naively this would be a loop of load-transform-store, but we found it faster to
|
| + // move the N+1th load ahead of the Nth store. We don't bother doing this for N<4.
|
| + Sk4f r, g, b, a;
|
| +
|
| + Sk4f y = (1.0f / 255.0f) * SkNx_cast<float, uint8_t>(Sk4b::Load(srcY));
|
| + Sk4f u = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcU)) - 128.0f);
|
| + Sk4f v = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcV)) - 128.0f);
|
| +
|
| + r = (y + 1.402f * v);
|
| + g = (y - 0.34414f * u - 0.71414f * v);
|
| + b = (y + 1.772f * u);
|
| +
|
| + r = srgb_to_linear(r);
|
| + g = srgb_to_linear(g);
|
| + b = srgb_to_linear(b);
|
| +
|
| + srcY += 4;
|
| + srcU += 4;
|
| + srcV += 4;
|
| + len -= 4;
|
| +
|
| + Sk4f dr, dg, db, da;
|
| + while (len >= 4) {
|
| + transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da);
|
| + translate_gamut(rTgTbT, dr, dg, db);
|
| +
|
| + y = (1.0f / 255.0f) * SkNx_cast<float, uint8_t>(Sk4b::Load(srcY));
|
| + u = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcU)) - 128.0f);
|
| + v = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcV)) - 128.0f);
|
| +
|
| + r = (y + 1.402f * v);
|
| + g = (y - 0.34414f * u - 0.71414f * v);
|
| + b = (y + 1.772f * u);
|
| +
|
| + r = srgb_to_linear(r);
|
| + g = srgb_to_linear(g);
|
| + b = srgb_to_linear(b);
|
| +
|
| + srcY += 4;
|
| + srcU += 4;
|
| + srcV += 4;
|
| + len -= 4;
|
| +
|
| + dr = sk_linear_to_srgb_needs_trunc(dr);
|
| + dg = sk_linear_to_srgb_needs_trunc(dg);
|
| + db = sk_linear_to_srgb_needs_trunc(db);
|
| +
|
| + dr = sk_clamp_0_255(dr);
|
| + dg = sk_clamp_0_255(dg);
|
| + db = sk_clamp_0_255(db);
|
| +
|
| + Sk4i rgba = (SkNx_cast<int>(dr) << 16)
|
| + | (SkNx_cast<int>(dg) << 8)
|
| + | (SkNx_cast<int>(db) << 0)
|
| + | (0xFF << 24 );
|
| + rgba.store(dst);
|
| + dst = SkTAddOffset<void>(dst, 4 * 4);
|
| + }
|
| +
|
| + transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da);
|
| + translate_gamut(rTgTbT, dr, dg, db);
|
| +
|
| + dr = sk_linear_to_srgb_needs_trunc(dr);
|
| + dg = sk_linear_to_srgb_needs_trunc(dg);
|
| + db = sk_linear_to_srgb_needs_trunc(db);
|
| +
|
| + dr = sk_clamp_0_255(dr);
|
| + dg = sk_clamp_0_255(dg);
|
| + db = sk_clamp_0_255(db);
|
| +
|
| + Sk4i rgba = (SkNx_cast<int>(dr) << 16)
|
| + | (SkNx_cast<int>(dg) << 8)
|
| + | (SkNx_cast<int>(db) << 0)
|
| + | (0xFF << 24 );
|
| + rgba.store(dst);
|
| + dst = SkTAddOffset<void>(dst, 4 * 4);
|
| + }
|
| +}
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>& space) {
|
|
|