Chromium Code Reviews| Index: src/core/SkColorSpaceXform.cpp |
| diff --git a/src/core/SkColorSpaceXform.cpp b/src/core/SkColorSpaceXform.cpp |
| index 1c0dd880e779669e2ae6ef186eb6ee1e342c29ac..baadd9a3cb1bca735740f2a2abf92cca601e39f8 100644 |
| --- a/src/core/SkColorSpaceXform.cpp |
| +++ b/src/core/SkColorSpaceXform.cpp |
| @@ -7,6 +7,7 @@ |
| #include "SkColorPriv.h" |
| #include "SkColorSpace_Base.h" |
| +#include "SkColorSpace_XYZTRC.h" |
| #include "SkColorSpacePriv.h" |
| #include "SkColorSpaceXform.h" |
| #include "SkHalf.h" |
| @@ -255,10 +256,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, |
|
msarett
2016/10/11 13:40:31
nit: fits on the previous line
|
| + 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 +271,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 +351,33 @@ std::unique_ptr<SkColorSpaceXform> SkColorSpaceXform::New(SkColorSpace* srcSpace |
| return nullptr; |
| } |
| + if (SkColorSpace_Base::Type::kA2B0 == as_CSB(dstSpace)->type()) { |
| + // A2B0 destinations not supported |
| + SkDebugf("A2B0 destinations not supported\n"); |
|
msarett
2016/10/11 13:40:31
Please SkColorSpacePrintf. Some people feel stron
|
| + return nullptr; |
| + } |
| + |
| + if (SkColorSpace_Base::Type::kA2B0 == as_CSB(srcSpace)->type()) { |
| + // TODO (raftias): return an A2B0-supporting SkColorSpaceXform here once the xform. |
| + // is implemented. SkColorSpaceXform_Base only supports XYZ+TRC based SkColorSpaces |
| + // Non-Lab A2B0 profiles are being temporarily converted to XYZ+TRC color spaces |
| + // using the same ignore a-curve/b-curve procedure as before so this should not |
| + // present an issue. |
| + //const SkColorSpace_A2B0* src = static_cast<const SkColorSpace_A2B0*>(srcSpace); |
| + //const SkColorSpace_XYZTRC* dst = static_cast<const SkColorSpace_XYZTRC*>(dstSpace); |
| + //return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_A2B0(src, dst)); |
| + return nullptr; |
| + } |
|
msarett
2016/10/11 13:40:31
nit: tabs
|
| + 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 +387,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 +499,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 +1120,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 +1144,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 +1244,6 @@ const |
| } |
| } |
| -#if defined(GOOGLE3) |
| - // 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 +1311,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)); |