diff options
author | Brian Osman <brianosman@google.com> | 2018-06-13 17:21:19 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-14 11:30:47 +0000 |
commit | f018b7d607a0859e2d6078578a9632144694072f (patch) | |
tree | 05967e1777d04753b1a5415eec53fbfcd170fc70 /src | |
parent | b57a861f183bfc6ae251297e3173faff0dc262f9 (diff) |
SkColorSpaceXformSteps improvements and tests
Added some helper functions and put the booleans in a nested struct
(this is motivated by upcoming changes). Added a unit test of steps
against skcms, with round-tripping in both combinations.
Change-Id: Iea3d60cd52edb5259b5576b1422ed6f856cde815
Reviewed-on: https://skia-review.googlesource.com/134660
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkColorSpaceXformSteps.cpp | 68 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformSteps.h | 28 |
2 files changed, 70 insertions, 26 deletions
diff --git a/src/core/SkColorSpaceXformSteps.cpp b/src/core/SkColorSpaceXformSteps.cpp index a084206aff..ae230ee0fc 100644 --- a/src/core/SkColorSpaceXformSteps.cpp +++ b/src/core/SkColorSpaceXformSteps.cpp @@ -17,13 +17,13 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr // We have some options about what to do with null src or dst here. SkASSERT(src && dst); - this->unpremul = srcAT == kPremul_SkAlphaType; - this->linearize = !src->gammaIsLinear(); - this->gamut_transform = src->toXYZD50Hash() != dst->toXYZD50Hash(); - this->encode = !dst->gammaIsLinear(); - this->premul = srcAT != kOpaque_SkAlphaType; + this->flags.unpremul = srcAT == kPremul_SkAlphaType; + this->flags.linearize = !src->gammaIsLinear(); + this->flags.gamut_transform = src->toXYZD50Hash() != dst->toXYZD50Hash(); + this->flags.encode = !dst->gammaIsLinear(); + this->flags.premul = srcAT != kOpaque_SkAlphaType; - if (this->gamut_transform && src->toXYZD50() && dst->fromXYZD50()) { + if (this->flags.gamut_transform && src->toXYZD50() && dst->fromXYZD50()) { auto xform = SkMatrix44(*dst->fromXYZD50(), *src->toXYZD50()); if (xform.get(3,0) == 0 && xform.get(3,1) == 0 && xform.get(3,2) == 0 && xform.get(3,3) == 1 && @@ -31,7 +31,7 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) { - this->src_to_dst_matrix[3*r+c] = xform.get(r,c); + this->src_to_dst_matrix[3*c+r] = xform.get(r,c); } } } @@ -44,22 +44,54 @@ SkColorSpaceXformSteps::SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType sr this->dstTFInv = dstTF.invert(); // If we linearize then immediately reencode with the same transfer function, skip both. - if ( this->linearize && - !this->gamut_transform && - this->encode && + if ( this->flags.linearize && + !this->flags.gamut_transform && + this->flags.encode && 0 == memcmp(&srcTF, &dstTF, sizeof(SkColorSpaceTransferFn))) { - this->linearize = false; - this->encode = false; + this->flags.linearize = false; + this->flags.encode = false; } // Skip unpremul...premul if there are no non-linear operations between. - if ( this->unpremul && - !this->linearize && - !this->encode && - this->premul) + if ( this->flags.unpremul && + !this->flags.linearize && + !this->flags.encode && + this->flags.premul) { - this->unpremul = false; - this->premul = false; + this->flags.unpremul = false; + this->flags.premul = false; + } +} + +void SkColorSpaceXformSteps::apply(float* rgba) const { + if (flags.unpremul) { + float invA = isfinite(1.0f / rgba[3]) ? 1.0f / rgba[3] : 0; + rgba[0] *= invA; + rgba[1] *= invA; + rgba[2] *= invA; + } + if (flags.linearize) { + rgba[0] = srcTF(rgba[0]); + rgba[1] = srcTF(rgba[1]); + rgba[2] = srcTF(rgba[2]); + } + if (flags.gamut_transform) { + float temp[3] = { rgba[0], rgba[1], rgba[2] }; + for (int i = 0; i < 3; ++i) { + rgba[i] = src_to_dst_matrix[ i] * temp[0] + + src_to_dst_matrix[3 + i] * temp[1] + + src_to_dst_matrix[6 + i] * temp[2]; + } + } + if (flags.encode) { + rgba[0] = dstTFInv(rgba[0]); + rgba[1] = dstTFInv(rgba[1]); + rgba[2] = dstTFInv(rgba[2]); + } + if (flags.premul) { + rgba[0] *= rgba[3]; + rgba[1] *= rgba[3]; + rgba[2] *= rgba[3]; } } diff --git a/src/core/SkColorSpaceXformSteps.h b/src/core/SkColorSpaceXformSteps.h index 6c38411692..3b2a88cddc 100644 --- a/src/core/SkColorSpaceXformSteps.h +++ b/src/core/SkColorSpaceXformSteps.h @@ -12,6 +12,22 @@ #include "SkImageInfo.h" struct SkColorSpaceXformSteps { + struct Flags { + bool unpremul; + bool linearize; + bool gamut_transform; + bool encode; + bool premul; + + uint32_t mask() const { + return (unpremul ? 1 : 0) + | (linearize ? 2 : 0) + | (gamut_transform ? 4 : 0) + | (encode ? 8 : 0) + | (premul ? 16 : 0); + } + }; + SkColorSpaceXformSteps(SkColorSpace* src, SkAlphaType srcAT, SkColorSpace* dst); @@ -22,17 +38,13 @@ struct SkColorSpaceXformSteps { return SkColorSpaceXformSteps(src, kOpaque_SkAlphaType, dst); } - bool unpremul; - bool linearize; - bool gamut_transform; - bool encode; - bool premul; + void apply(float rgba[4]) const; + + Flags flags; SkColorSpaceTransferFn srcTF, // Apply for linearize. dstTFInv; // Apply for encode. - float src_to_dst_matrix[9]; // Apply this 3x3 row-major matrix for gamut_transform. + float src_to_dst_matrix[9]; // Apply this 3x3 column-major matrix for gamut_transform. }; - - #endif//SkColorSpaceXformSteps_DEFINED |