diff options
author | raftias <raftias@google.com> | 2016-11-11 15:27:39 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-11-11 15:27:39 -0800 |
commit | 2563601fc2b0505619f905f86bd249ae630197cc (patch) | |
tree | a6956629c520bccdc8a5fd307d5ad0650525bdf8 /src/core/SkColorLookUpTable.cpp | |
parent | 6e9ac12495f3b64b6ea8860bb9f99c43cd33aa08 (diff) |
Initial implementation of a SkColorSpace_A2B xform
There is support for all features of SkColorSpace_A2B.
Tests for these functionality were adapted from
the XYZ xform, plus a CLUT-specific test was added.
Shared functions used by both SkColorSpaceXform_XYZ and SkColorSpaceXform_A2B
have been moved into a shared header.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2449243003
CQ_INCLUDE_TRYBOTS=master.client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot
Review-Url: https://codereview.chromium.org/2449243003
Diffstat (limited to 'src/core/SkColorLookUpTable.cpp')
-rw-r--r-- | src/core/SkColorLookUpTable.cpp | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/src/core/SkColorLookUpTable.cpp b/src/core/SkColorLookUpTable.cpp new file mode 100644 index 0000000000..73f3e8836c --- /dev/null +++ b/src/core/SkColorLookUpTable.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkColorLookUpTable.h" +#include "SkFloatingPoint.h" + +void SkColorLookUpTable::interp3D(float dst[3], float src[3]) const { + // Call the src components x, y, and z. + const uint8_t maxX = fGridPoints[0] - 1; + const uint8_t maxY = fGridPoints[1] - 1; + const uint8_t maxZ = fGridPoints[2] - 1; + + // An approximate index into each of the three dimensions of the table. + const float x = src[0] * maxX; + const float y = src[1] * maxY; + const 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. + const float diffX = x - ix; + const float diffY = y - iy; + const 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 * fGridPoints[1] * fGridPoints[2]; + const int n010 = 3 * 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 = &(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++; + } +} |