Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Unified Diff: src/core/SkColorSpaceXform.cpp

Issue 2341143002: YUV and color xforms
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« no previous file with comments | « src/core/SkColorSpaceXform.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698