Lines Matching refs:tf

131 // For exotic HDR transfer functions, we encode them using a tf.g that makes no sense,
145 static TFKind classify(const skcms_TransferFunction& tf, TF_PQish* pq = nullptr
147 if (tf.g < 0 && (int)tf.g == tf.g) {
149 switch ((int)tf.g) {
150 case -PQish: if (pq ) { memcpy(pq , &tf.a, sizeof(*pq )); } return PQish;
151 case -HLGish: if (hlg) { memcpy(hlg, &tf.a, sizeof(*hlg)); } return HLGish;
152 case -HLGinvish: if (hlg) { memcpy(hlg, &tf.a, sizeof(*hlg)); } return HLGinvish;
158 if (isfinitef_(tf.a + tf.b + tf.c + tf.d + tf.e + tf.f + tf.g)
160 && tf.a >= 0
161 && tf.c >= 0
162 && tf.d >= 0
163 && tf.g >= 0
164 // Raising a negative value to a fractional tf->g produces complex numbers.
165 && tf.a * tf.d + tf.b >= 0) {
172 bool skcms_TransferFunction_isSRGBish(const skcms_TransferFunction* tf) {
173 return classify(*tf) == sRGBish;
175 bool skcms_TransferFunction_isPQish(const skcms_TransferFunction* tf) {
176 return classify(*tf) == PQish;
178 bool skcms_TransferFunction_isHLGish(const skcms_TransferFunction* tf) {
179 return classify(*tf) == HLGish;
182 bool skcms_TransferFunction_makePQish(skcms_TransferFunction* tf,
185 *tf = { TFKind_marker(PQish), A,B,C,D,E,F };
186 assert(skcms_TransferFunction_isPQish(tf));
190 bool skcms_TransferFunction_makeScaledHLGish(skcms_TransferFunction* tf,
193 *tf = { TFKind_marker(HLGish), R,G, a,b,c, K-1.0f };
194 assert(skcms_TransferFunction_isHLGish(tf));
198 float skcms_TransferFunction_eval(const skcms_TransferFunction* tf, float x) {
204 switch (classify(*tf, &pq, &hlg)) {
222 case sRGBish: return sign * (x < tf->d ? tf->c * x + tf->f
223 : powf_(tf->a * x + tf->b, tf->g) + tf->e);
1956 // tf(x) = cx + f x < d
1957 // tf(x) = (ax + b)^g + e x ≥ d
1965 // tf(x) = cx + f x < d
1966 // tf(x) = (ax + b)^g - (ad + b)^g + cd + f x ≥ d
1993 const skcms_TransferFunction* tf,
1997 const float g = tf->g, a = tf->a, b = tf->b,
1998 c = tf->c, d = tf->d, f = tf->f;
2020 skcms_TransferFunction* tf,
2024 // Let P = [ tf->g, tf->a, tf->b ] (the three terms that we're adjusting).
2067 float resid = rg_nonlinear(x,curve,tf, dfdP);
2094 tf->g += dP.vals[0];
2095 tf->a += dP.vals[1];
2096 tf->b += dP.vals[2];
2097 return isfinitef_(tf->g) && isfinitef_(tf->a) && isfinitef_(tf->b);
2102 skcms_TransferFunction tf;
2103 if (!skcms_TransferFunction_invert(tf_inv, &tf) || sRGBish != classify(tf)) {
2108 if (!skcms_TransferFunction_invert(&tf, &tf_inv_again)) {
2115 // Fit the points in [L,N) to the non-linear piece of tf, or return false if we can't.
2116 static bool fit_nonlinear(const skcms_Curve* curve, int L, int N, skcms_TransferFunction* tf) {
2118 auto fixup_tf = [tf]() {
2121 if (tf->a < 0) {
2126 if (tf->a * tf->d + tf->b < 0) {
2127 tf->b = -tf->a * tf->d;
2129 assert (tf->a >= 0 &&
2130 tf->a * tf->d + tf->b >= 0);
2134 tf->e = tf->c*tf->d + tf->f
2135 - powf_(tf->a*tf->d + tf->b, tf->g);
2147 skcms_TransferFunction best_tf = *tf;
2151 float init_error = max_roundtrip_error_checked(curve, tf);
2154 best_tf = *tf;
2159 if (!gauss_newton_step(curve, tf, L*dx, dx, N-L) || !fixup_tf()) {
2160 *tf = best_tf;
2164 float max_error = max_roundtrip_error_checked(curve, tf);
2167 best_tf = *tf;
2171 *tf = best_tf;
2198 skcms_TransferFunction tf,
2202 tf.f = 0.0f;
2203 int L = fit_linear(curve, N, kTolerances[t], &tf.c, &tf.d);
2208 tf.g = 1;
2209 tf.a = tf.c;
2210 tf.b = tf.f;
2211 tf.c = tf.d = tf.e = tf.f = 0;
2214 tf.g = 1;
2215 tf.a = (eval_curve(curve, (N-1)*dx) -
2218 tf.b = eval_curve(curve, (N-2)*dx)
2219 - tf.a * (N-2)*dx;
2220 tf.e = 0;
2226 tf.g = log2f_(mid_y) / log2f_(mid_x);
2227 tf.a = 1;
2228 tf.b = 0;
2229 tf.e = tf.c*tf.d + tf.f
2230 - powf_(tf.a*tf.d + tf.b, tf.g);
2233 if (!skcms_TransferFunction_invert(&tf, &tf_inv) ||
2238 // We fit tf_inv, so calculate tf to keep in sync.
2240 if (!skcms_TransferFunction_invert(&tf_inv, &tf)) {
2248 // anything else is just some accident of math and the way we pun tf.g as a type flag.
2250 if (sRGBish != classify(tf)) {
2259 // We've kept tf and tf_inv in sync above, but we can't guarantee that tf is
2263 if (!skcms_TransferFunction_invert(&tf, &tf_inv)) {
2270 *approx = tf;
2535 const skcms_TransferFunction& tf = curve->parametric;
2537 if (tf.g == 1 && tf.a == 1 &&
2538 tf.b == 0 && tf.c == 0 && tf.d == 0 && tf.e == 0 && tf.f == 0) {
2542 switch (classify(tf)) {
2544 case sRGBish: return OpAndArg{op.sRGBish, &tf};
2545 case PQish: return OpAndArg{op.PQish, &tf};
2546 case HLGish: return OpAndArg{op.HLGish, &tf};
2547 case HLGinvish: return OpAndArg{op.HLGinvish, &tf};
2975 skcms_TransferFunction tf[3];
2980 tf[i] = profile->trc[i].parametric;
2986 if (!skcms_ApproximateCurve(&profile->trc[i], &tf[i], &max_error)) {
2993 profile->trc[i].parametric = tf[i];