Chromium Code Reviews| Index: src/core/SkColorSpaceXformPriv.h |
| diff --git a/src/core/SkColorSpaceXformPriv.h b/src/core/SkColorSpaceXformPriv.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b300023aa9a1b7cacf05196d716395e830585688 |
| --- /dev/null |
| +++ b/src/core/SkColorSpaceXformPriv.h |
| @@ -0,0 +1,106 @@ |
| +/* |
| + * Copyright 2016 Google Inc. |
|
msarett
2016/10/11 13:40:31
Please remove
raftias
2016/10/14 17:10:15
Oops, I forgot to git rm it.
|
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#ifndef SkColorSpaceXformPriv_DEFINED |
| +#define SkColorSpaceXformPriv_DEFINED |
| + |
| +#include "SkColorSpace_Base.h" |
| +#include "SkSRGB.h" |
| + |
| +inline 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++; |
| + } |
| +} |
| + |
| +#endif |