Index: src/core/SkColorSpaceXform.cpp |
diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp |
index 1c0dd880e779669e2ae6ef186eb6ee1e342c29ac..67115c8c220aa636d069f12378be7752c0e26a2f 100644 |
--- a/src/core/SkColorSpaceXform.cpp |
+++ b/src/core/SkColorSpaceXform.cpp |
@@ -7,8 +7,10 @@ |
#include "SkColorPriv.h" |
#include "SkColorSpace_Base.h" |
+#include "SkColorSpace_XYZTRC.h" |
#include "SkColorSpacePriv.h" |
#include "SkColorSpaceXform.h" |
+#include "SkColorSpaceXformPriv.h" |
#include "SkHalf.h" |
#include "SkOpts.h" |
#include "SkSRGB.h" |
@@ -255,10 +257,11 @@ static const GammaFns<uint8_t> kFromLinear { |
// Build tables to transform src gamma to linear. |
template <typename T> |
-static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, int gammaTableSize, |
- SkColorSpace* space, const GammaFns<T>& fns, bool gammasAreMatching) |
+static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, |
+ int gammaTableSize, const SkColorSpace_XYZTRC* space, |
+ const GammaFns<T>& fns,bool gammasAreMatching) |
{ |
- switch (as_CSB(space)->gammaNamed()) { |
+ switch (space->gammaNamed()) { |
case kSRGB_SkGammaNamed: |
outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = fns.fSRGBTable; |
break; |
@@ -269,7 +272,7 @@ static void build_gamma_tables(const T* outGammaTables[3], T* gammaTableStorage, |
outGammaTables[0] = outGammaTables[1] = outGammaTables[2] = nullptr; |
break; |
default: { |
- const SkGammas* gammas = as_CSB(space)->gammas(); |
+ const SkGammas* gammas = space->gammas(); |
SkASSERT(gammas); |
auto build_table = [=](int i) { |
@@ -349,13 +352,28 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace |
return nullptr; |
} |
+ if (as_CSB(dstSpace)->type() == SkColorSpace_Base::Type::kA2B0) { |
msarett
2016/10/07 01:48:35
nit: Skia style
Constants come first in == compar
raftias
2016/10/10 20:37:32
Done.
|
+ // A2B0 destinations not supported |
+ return nullptr; |
+ } |
+ |
+ // Check whether we need to to an A2B0 transformation |
msarett
2016/10/07 01:48:35
Don't think there's a need for this comment, the c
raftias
2016/10/10 20:37:32
Done.
|
+ if (as_CSB(srcSpace)->type() == SkColorSpace_Base::Type::kA2B0) { |
msarett
2016/10/07 01:48:35
Same nit as above.
raftias
2016/10/10 20:37:32
Done.
|
+ // TODO (raftias): create a A2B0-supporting SkColorSpaceXform here once implemented |
+ // as SkColorSpaceXform_Base only supports XYZ+TRC based SkColorSpaces |
msarett
2016/10/07 01:48:35
nit: I think this comment could be worded a little
raftias
2016/10/10 20:37:32
Done.
|
+ return nullptr; |
+ } |
+ const SkColorSpace_XYZTRC* srcSpaceXYZ = static_cast<const SkColorSpace_XYZTRC*>(srcSpace); |
+ const SkColorSpace_XYZTRC* dstSpaceXYZ = static_cast<const SkColorSpace_XYZTRC*>(dstSpace); |
+ |
+ |
ColorSpaceMatch csm = kNone_ColorSpaceMatch; |
SkMatrix44 srcToDst(SkMatrix44::kUninitialized_Constructor); |
- if (SkColorSpace::Equals(srcSpace, dstSpace)) { |
+ if (SkColorSpace::Equals(srcSpaceXYZ, dstSpaceXYZ)) { |
srcToDst.setIdentity(); |
csm = kFull_ColorSpaceMatch; |
} else { |
- srcToDst.setConcat(as_CSB(dstSpace)->fromXYZD50(), as_CSB(srcSpace)->toXYZD50()); |
+ srcToDst.setConcat(dstSpaceXYZ->fromXYZD50(), srcSpaceXYZ->toXYZD50()); |
if (is_almost_identity(srcToDst)) { |
srcToDst.setIdentity(); |
@@ -365,109 +383,109 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace |
switch (csm) { |
case kNone_ColorSpaceMatch: |
- switch (as_CSB(dstSpace)->gammaNamed()) { |
+ switch (dstSpaceXYZ->gammaNamed()) { |
case kSRGB_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kSRGB_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
case k2Dot2Curve_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, k2Dot2_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
case kLinear_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kLinear_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
default: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
} |
case kGamut_ColorSpaceMatch: |
- switch (as_CSB(dstSpace)->gammaNamed()) { |
+ switch (dstSpaceXYZ->gammaNamed()) { |
case kSRGB_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kSRGB_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
case k2Dot2Curve_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, k2Dot2_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
case kLinear_SkGammaNamed: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kLinear_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
default: |
- if (srcSpace->gammaIsLinear()) { |
+ if (srcSpaceXYZ->gammaIsLinear()) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} else { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kTable_DstGamma, kGamut_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
} |
case kFull_ColorSpaceMatch: |
- switch (as_CSB(dstSpace)->gammaNamed()) { |
+ switch (dstSpaceXYZ->gammaNamed()) { |
case kSRGB_SkGammaNamed: |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kSRGB_DstGamma, kFull_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
case k2Dot2Curve_SkGammaNamed: |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, k2Dot2_DstGamma, kFull_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
case kLinear_SkGammaNamed: |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kLinear_SrcGamma, kLinear_DstGamma, kFull_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
default: |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kTable_DstGamma, kFull_ColorSpaceMatch> |
- (srcSpace, srcToDst, dstSpace)); |
+ (srcSpaceXYZ, srcToDst, dstSpaceXYZ)); |
} |
default: |
SkASSERT(false); |
@@ -477,137 +495,6 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
-static float byte_to_float(uint8_t byte) { |
- return ((float) byte) * (1.0f / 255.0f); |
-} |
- |
-// Clamp to the 0-1 range. |
-static float clamp_normalized_float(float v) { |
- if (v > 1.0f) { |
- return 1.0f; |
- } else if ((v < 0.0f) || (v != v)) { |
- return 0.0f; |
- } else { |
- return v; |
- } |
-} |
- |
-static void interp_3d_clut(float dst[3], float src[3], const SkColorLookUpTable* colorLUT) { |
- // Call the src components x, y, and z. |
- uint8_t maxX = colorLUT->fGridPoints[0] - 1; |
- uint8_t maxY = colorLUT->fGridPoints[1] - 1; |
- uint8_t maxZ = colorLUT->fGridPoints[2] - 1; |
- |
- // An approximate index into each of the three dimensions of the table. |
- float x = src[0] * maxX; |
- float y = src[1] * maxY; |
- float z = src[2] * maxZ; |
- |
- // This gives us the low index for our interpolation. |
- int ix = sk_float_floor2int(x); |
- int iy = sk_float_floor2int(y); |
- int iz = sk_float_floor2int(z); |
- |
- // Make sure the low index is not also the max index. |
- ix = (maxX == ix) ? ix - 1 : ix; |
- iy = (maxY == iy) ? iy - 1 : iy; |
- iz = (maxZ == iz) ? iz - 1 : iz; |
- |
- // Weighting factors for the interpolation. |
- float diffX = x - ix; |
- float diffY = y - iy; |
- float diffZ = z - iz; |
- |
- // Constants to help us navigate the 3D table. |
- // Ex: Assume x = a, y = b, z = c. |
- // table[a * n001 + b * n010 + c * n100] logically equals table[a][b][c]. |
- const int n000 = 0; |
- const int n001 = 3 * colorLUT->fGridPoints[1] * colorLUT->fGridPoints[2]; |
- const int n010 = 3 * colorLUT->fGridPoints[2]; |
- const int n011 = n001 + n010; |
- const int n100 = 3; |
- const int n101 = n100 + n001; |
- const int n110 = n100 + n010; |
- const int n111 = n110 + n001; |
- |
- // Base ptr into the table. |
- const float* ptr = &(colorLUT->table()[ix*n001 + iy*n010 + iz*n100]); |
- |
- // The code below performs a tetrahedral interpolation for each of the three |
- // dst components. Once the tetrahedron containing the interpolation point is |
- // identified, the interpolation is a weighted sum of grid values at the |
- // vertices of the tetrahedron. The claim is that tetrahedral interpolation |
- // provides a more accurate color conversion. |
- // blogs.mathworks.com/steve/2006/11/24/tetrahedral-interpolation-for-colorspace-conversion/ |
- // |
- // I have one test image, and visually I can't tell the difference between |
- // tetrahedral and trilinear interpolation. In terms of computation, the |
- // tetrahedral code requires more branches but less computation. The |
- // SampleICC library provides an option for the client to choose either |
- // tetrahedral or trilinear. |
- for (int i = 0; i < 3; i++) { |
- if (diffZ < diffY) { |
- if (diffZ < diffX) { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n110] - ptr[n010]) + |
- diffY * (ptr[n010] - ptr[n000]) + |
- diffX * (ptr[n111] - ptr[n110])); |
- } else if (diffY < diffX) { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + |
- diffY * (ptr[n011] - ptr[n001]) + |
- diffX * (ptr[n001] - ptr[n000])); |
- } else { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n111] - ptr[n011]) + |
- diffY * (ptr[n010] - ptr[n000]) + |
- diffX * (ptr[n011] - ptr[n010])); |
- } |
- } else { |
- if (diffZ < diffX) { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n101] - ptr[n001]) + |
- diffY * (ptr[n111] - ptr[n101]) + |
- diffX * (ptr[n001] - ptr[n000])); |
- } else if (diffY < diffX) { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + |
- diffY * (ptr[n111] - ptr[n101]) + |
- diffX * (ptr[n101] - ptr[n100])); |
- } else { |
- dst[i] = (ptr[n000] + diffZ * (ptr[n100] - ptr[n000]) + |
- diffY * (ptr[n110] - ptr[n100]) + |
- diffX * (ptr[n111] - ptr[n110])); |
- } |
- } |
- |
- // Increment the table ptr in order to handle the next component. |
- // Note that this is the how table is designed: all of nXXX |
- // variables are multiples of 3 because there are 3 output |
- // components. |
- ptr++; |
- } |
-} |
- |
-static void handle_color_lut(uint32_t* dst, const uint32_t* src, int len, |
- SkColorLookUpTable* colorLUT) { |
- while (len-- > 0) { |
- uint8_t r = (*src >> 0) & 0xFF, |
- g = (*src >> 8) & 0xFF, |
- b = (*src >> 16) & 0xFF; |
- |
- float in[3]; |
- float out[3]; |
- in[0] = byte_to_float(r); |
- in[1] = byte_to_float(g); |
- in[2] = byte_to_float(b); |
- interp_3d_clut(out, in, colorLUT); |
- |
- r = sk_float_round2int(255.0f * clamp_normalized_float(out[0])); |
- g = sk_float_round2int(255.0f * clamp_normalized_float(out[1])); |
- b = sk_float_round2int(255.0f * clamp_normalized_float(out[2])); |
- *dst = SkPackARGB_as_RGBA(0xFF, r, g, b); |
- |
- src++; |
- dst++; |
- } |
-} |
- |
static inline void load_matrix(const float matrix[16], |
Sk4f& rXgXbX, Sk4f& rYgYbY, Sk4f& rZgZbZ, Sk4f& rTgTbT) { |
rXgXbX = Sk4f::Load(matrix + 0); |
@@ -1229,14 +1116,14 @@ static void color_xform_RGBA(void* dst, const uint32_t* src, int len, |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
-static inline int num_tables(SkColorSpace* space) { |
- switch (as_CSB(space)->gammaNamed()) { |
+static inline int num_tables(const SkColorSpace_XYZTRC* space) { |
+ switch (space->gammaNamed()) { |
case kSRGB_SkGammaNamed: |
case k2Dot2Curve_SkGammaNamed: |
case kLinear_SkGammaNamed: |
return 0; |
default: { |
- const SkGammas* gammas = as_CSB(space)->gammas(); |
+ const SkGammas* gammas = space->gammas(); |
SkASSERT(gammas); |
bool gammasAreMatching = (gammas->type(0) == gammas->type(1)) && |
@@ -1253,8 +1140,8 @@ static inline int num_tables(SkColorSpace* space) { |
template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> |
SkColorSpaceXform_Base<kSrc, kDst, kCSM> |
-::SkColorSpaceXform_Base(SkColorSpace* srcSpace, const SkMatrix44& srcToDst, SkColorSpace* dstSpace) |
- : fColorLUT(sk_ref_sp((SkColorLookUpTable*) as_CSB(srcSpace)->colorLUT())) |
+::SkColorSpaceXform_Base(const SkColorSpace_XYZTRC* srcSpace, const SkMatrix44& srcToDst, |
+ const SkColorSpace_XYZTRC* dstSpace) |
{ |
srcToDst.asColMajorf(fSrcToDst); |
@@ -1353,19 +1240,6 @@ const |
} |
} |
-#if defined(GOOGLE3) |
msarett
2016/10/07 01:48:35
Make me feel good to see this deleted...
|
- // Stack frame size is limited in GOOGLE3. |
- SkAutoSMalloc<256 * sizeof(uint32_t)> storage; |
-#else |
- SkAutoSMalloc<1024 * sizeof(uint32_t)> storage; |
-#endif |
- if (fColorLUT) { |
- size_t storageBytes = len * sizeof(uint32_t); |
- storage.reset(storageBytes); |
- handle_color_lut((uint32_t*) storage.get(), src, len, fColorLUT.get()); |
- src = (const uint32_t*) storage.get(); |
- } |
- |
switch (dstColorFormat) { |
case kRGBA_8888_ColorFormat: |
switch (kDst) { |
@@ -1433,7 +1307,7 @@ const |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
-std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(SkColorSpace* space) { |
+std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const SkColorSpace_XYZTRC* space) { |
return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
<kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> |
(space, SkMatrix::I(), space)); |