diff options
author | skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com> | 2018-05-17 17:58:48 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-05-17 18:40:14 +0000 |
commit | 86168a1972c23221a3900f5b8c1eab0480109fc4 (patch) | |
tree | a36b22f3f700df6ad68eb0c9626d8d7df394d050 /third_party/skcms/src/PolyTF.c | |
parent | 29ede9b0c31c611bbd56799676c3b0b35bc20942 (diff) |
Roll skia/third_party/skcms 06d773b..3f444c5 (1 commits)
https://skia.googlesource.com/skcms.git/+log/06d773b..3f444c5
2018-05-17 mtklein@chromium.org rm skcms_PolyTF and skcms_OptimizeForSpeed()
The AutoRoll server is located here: https://skcms-skia-roll.skia.org
Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md
If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.
CQ_INCLUDE_TRYBOTS=master.tryserver.blink:linux_trusty_blink_rel
TBR=herb@google.com
Change-Id: Ibdab92aa3d3cd9cc478623051ad1abb915765a7e
Reviewed-on: https://skia-review.googlesource.com/128981
Reviewed-by: skcms-skia-autoroll <skcms-skia-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
Diffstat (limited to 'third_party/skcms/src/PolyTF.c')
-rw-r--r-- | third_party/skcms/src/PolyTF.c | 175 |
1 files changed, 0 insertions, 175 deletions
diff --git a/third_party/skcms/src/PolyTF.c b/third_party/skcms/src/PolyTF.c deleted file mode 100644 index f74cf5418d..0000000000 --- a/third_party/skcms/src/PolyTF.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "../skcms.h" -#include "Curve.h" -#include "GaussNewton.h" -#include "Macros.h" -#include "PortableMath.h" -#include "TransferFunction.h" -#include <limits.h> -#include <stdlib.h> - -// f(x) = skcms_PolyTF{A,B,C,D}(x) = -// Cx x < D -// A(x^3-1) + B(x^2-1) + 1 x ≥ D -// -// We'll fit C and D directly, and then hold them constant -// and fit the other part using Gauss-Newton, subject to -// the constraint that both parts meet at x=D: -// -// CD = A(D^3-1) + B(D^2-1) + 1 -// -// This lets us solve for B, reducing the optimization problem -// for that part down to just a single parameter A: -// -// CD - A(D^3-1) - 1 -// B = ----------------- -// D^2-1 -// -// x^2-1 -// f(x) = A(x^3-1) + ----- [CD - A(D^3-1) - 1] + 1 -// D^2-1 -// -// (x^2-1) (D^3-1) -// ∂f/∂A = x^3-1 - --------------- -// D^2-1 -// -// It's important to evaluate as f(x) as A(x^3-1) + B(x^2-1) + 1 -// and not Ax^3 + Bx^2 + (1-A-B) to ensure that f(1.0f) == 1.0f. - - -static float eval_poly_tf(float A, float B, float C, float D, - float x) { - return x < D ? C*x - : A*(x*x*x-1) + B*(x*x-1) + 1; -} - -typedef struct { - const skcms_Curve* curve; - const skcms_PolyTF* tf; -} rg_poly_tf_arg; - -static float rg_poly_tf(float x, const void* ctx, const float P[3], float dfdP[3]) { - const rg_poly_tf_arg* arg = (const rg_poly_tf_arg*)ctx; - const skcms_PolyTF* tf = arg->tf; - - float A = P[0], - C = tf->C, - D = tf->D; - float B = (C*D - A*(D*D*D - 1) - 1) / (D*D - 1); - - dfdP[0] = (x*x*x - 1) - (x*x-1)*(D*D*D-1)/(D*D-1); - - return skcms_eval_curve(arg->curve, x) - - eval_poly_tf(A,B,C,D, x); -} - -static bool fit_poly_tf(const skcms_Curve* curve, skcms_PolyTF* tf) { - if (curve->table_entries > (uint32_t)INT_MAX) { - return false; - } - - const int N = curve->table_entries == 0 ? 256 - : (int)curve->table_entries; - const float dx = 1.0f / (N-1); - - // We'll test the quality of our fit by roundtripping through a skcms_TransferFunction, - // either the inverse of the curve itself if it is parametric, or of its approximation if not. - skcms_TransferFunction baseline; - float err; - if (curve->table_entries == 0) { - baseline = curve->parametric; - } else if (!skcms_ApproximateCurve(curve, &baseline, &err)) { - return false; - } - - // We'll borrow the linear section from baseline, which is either - // exactly correct, or already the approximation we'd use anyway. - tf->C = baseline.c; - tf->D = baseline.d; - if (baseline.f != 0) { - return false; // Can't fit this (rare) kind of curve here. - } - - // Detect linear baseline: (ax + b)^g + e --> ax ~~> Cx - if (baseline.g == 1 && baseline.d == 0) { - if (baseline.b + baseline.e == 0) { - tf->A = 0; - tf->B = 0; - tf->C = baseline.a; - tf->D = INFINITY_; // Always use Cx, never Ax^3+Bx^2+(1-A-B) - return true; - } else { - return false; // Just like baseline.f != 0 above, can't represent this offset. - } - } - - // This case is less likely, but also guards against divide by zero below. - if (tf->D == 1) { - tf->A = 0; - tf->B = 0; - return true; - } - - // Number of points already fit in the linear section. - // If the curve isn't parametric and we approximated instead, this should be exact. - // const int L = (int)( tf->D/dx + 0.5f ) + 1 - const int L = (int)(tf->D * (N-1) + 0.5f) + 1; - - if (L == N-1) { - // All points but one fit the linear section. - // We could connect the last point with a quadratic, but let's just be lazy. - return false; - } - - skcms_TransferFunction inv; - if (!skcms_TransferFunction_invert(&baseline, &inv)) { - return false; - } - - // Start with guess A = 0, i.e. f(x) ≈ x^2. - float P[3] = {0, 0,0}; - for (int i = 0; i < 3; i++) { - rg_poly_tf_arg arg = { curve, tf }; - if (!skcms_gauss_newton_step(rg_poly_tf, &arg, - P, - L*dx, dx, N-L)) { - return false; - } - } - - float A = tf->A = P[0], - C = tf->C, - D = tf->D, - B = tf->B = (C*D - A*(D*D*D - 1) - 1) / (D*D - 1); - - for (int i = 0; i < N; i++) { - float x = i * (1.0f/(N-1)); - - float rt = skcms_TransferFunction_eval(&inv, eval_poly_tf(A,B,C,D, x)) - * (N-1) + 0.5f; - if (!isfinitef_(rt) || rt >= N || rt < 0) { - return false; - } - - const int tol = (i == 0 || i == N-1) ? 0 - : N/256; - if (abs(i - (int)rt) > tol) { - return false; - } - } - return true; -} - -void skcms_OptimizeForSpeed(skcms_ICCProfile* profile) { - for (int i = 0; profile->has_trc && i < 3; i++) { - if (!profile->has_poly_tf[i]) { - profile->has_poly_tf[i] = fit_poly_tf(&profile->trc[i], &profile->poly_tf[i]); - } - } -} |