aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2017-03-14 11:27:13 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-03-14 15:57:03 +0000
commit73e627074839bc00569117235eb4e7d4fc3cc39f (patch)
tree344fcfeba2fc78066f59347adce4c0d55bc19c06 /src/core
parentdce25909ac0e84ee73640fd49dd3b82f66dd4ce1 (diff)
Expose SkColorSpaceTransferFn inversion function
Also adds tolerance to checks against zero BUG=skia: Change-Id: I2ad5737c6eef7e3ed52a685dceb347a434607336 Reviewed-on: https://skia-review.googlesource.com/9643 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: Matt Sarett <msarett@google.com>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkColorSpace.cpp44
-rw-r--r--src/core/SkColorSpaceXform_A2B.cpp48
2 files changed, 45 insertions, 47 deletions
diff --git a/src/core/SkColorSpace.cpp b/src/core/SkColorSpace.cpp
index 3677fb6342..8ffff5edf3 100644
--- a/src/core/SkColorSpace.cpp
+++ b/src/core/SkColorSpace.cpp
@@ -632,3 +632,47 @@ bool SkColorSpace::Equals(const SkColorSpace* src, const SkColorSpace* dst) {
serializedSrcData->size());
}
}
+
+SkColorSpaceTransferFn SkColorSpaceTransferFn::invert() const {
+ // Original equation is: y = (ax + b)^g + e for x >= d
+ // y = cx + f otherwise
+ //
+ // so 1st inverse is: (y - e)^(1/g) = ax + b
+ // x = ((y - e)^(1/g) - b) / a
+ //
+ // which can be re-written as: x = (1/a)(y - e)^(1/g) - b/a
+ // x = ((1/a)^g)^(1/g) * (y - e)^(1/g) - b/a
+ // x = ([(1/a)^g]y + [-((1/a)^g)e]) ^ [1/g] + [-b/a]
+ //
+ // and 2nd inverse is: x = (y - f) / c
+ // which can be re-written as: x = [1/c]y + [-f/c]
+ //
+ // and now both can be expressed in terms of the same parametric form as the
+ // original - parameters are enclosed in square brackets.
+ SkColorSpaceTransferFn inv = { 0, 0, 0, 0, 0, 0, 0 };
+
+ // find inverse for linear segment (if possible)
+ if (!transfer_fn_almost_equal(0.f, fC)) {
+ inv.fC = 1.f / fC;
+ inv.fF = -fF / fC;
+ } else {
+ // otherwise assume it should be 0 as it is the lower segment
+ // as y = f is a constant function
+ }
+
+ // find inverse for the other segment (if possible)
+ if (transfer_fn_almost_equal(0.f, fA) || transfer_fn_almost_equal(0.f, fG)) {
+ // otherwise assume it should be 1 as it is the top segment
+ // as you can't invert the constant functions y = b^g + c, or y = 1 + c
+ inv.fG = 1.f;
+ inv.fE = 1.f;
+ } else {
+ inv.fG = 1.f / fG;
+ inv.fA = powf(1.f / fA, fG);
+ inv.fB = -inv.fA * fE;
+ inv.fE = -fB / fA;
+ }
+ inv.fD = fC * fD + fF;
+
+ return inv;
+}
diff --git a/src/core/SkColorSpaceXform_A2B.cpp b/src/core/SkColorSpaceXform_A2B.cpp
index 39c352cd8c..cde07f57cf 100644
--- a/src/core/SkColorSpaceXform_A2B.cpp
+++ b/src/core/SkColorSpaceXform_A2B.cpp
@@ -88,52 +88,6 @@ static inline bool gamma_to_parametric(SkColorSpaceTransferFn* coeffs, const SkG
return false;
}
}
-static inline SkColorSpaceTransferFn invert_parametric(const SkColorSpaceTransferFn& fn) {
- // Original equation is: y = (ax + b)^g + e for x >= d
- // y = cx + f otherwise
- //
- // so 1st inverse is: (y - e)^(1/g) = ax + b
- // x = ((y - e)^(1/g) - b) / a
- //
- // which can be re-written as: x = (1/a)(y - e)^(1/g) - b/a
- // x = ((1/a)^g)^(1/g) * (y - e)^(1/g) - b/a
- // x = ([(1/a)^g]y + [-((1/a)^g)e]) ^ [1/g] + [-b/a]
- //
- // and 2nd inverse is: x = (y - f) / c
- // which can be re-written as: x = [1/c]y + [-f/c]
- //
- // and now both can be expressed in terms of the same parametric form as the
- // original - parameters are enclosed in square brackets.
-
- // find inverse for linear segment (if possible)
- float c, f;
- if (0.f == fn.fC) {
- // otherwise assume it should be 0 as it is the lower segment
- // as y = f is a constant function
- c = 0.f;
- f = 0.f;
- } else {
- c = 1.f / fn.fC;
- f = -fn.fF / fn.fC;
- }
- // find inverse for the other segment (if possible)
- float g, a, b, e;
- if (0.f == fn.fA || 0.f == fn.fG) {
- // otherwise assume it should be 1 as it is the top segment
- // as you can't invert the constant functions y = b^g + c, or y = 1 + c
- g = 1.f;
- a = 0.f;
- b = 0.f;
- e = 1.f;
- } else {
- g = 1.f / fn.fG;
- a = powf(1.f / fn.fA, fn.fG);
- b = -a * fn.fE;
- e = -fn.fB / fn.fA;
- }
- const float d = fn.fC * fn.fD + fn.fF;
- return {g, a, b, c, d, e, f};
-}
SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
SkColorSpace_XYZ* dstSpace)
@@ -279,7 +233,7 @@ SkColorSpaceXform_A2B::SkColorSpaceXform_A2B(SkColorSpace_A2B* srcSpace,
} else {
SkColorSpaceTransferFn fn;
SkAssertResult(gamma_to_parametric(&fn, gammas, channel));
- this->addTransferFn(invert_parametric(fn), channel);
+ this->addTransferFn(fn.invert(), channel);
}
}
}