Lines Matching refs:curve
233 static float eval_curve(const skcms_Curve* curve, float x) {
234 if (curve->table_entries == 0) {
235 return skcms_TransferFunction_eval(&curve->parametric, x);
238 float ix = fmaxf_(0, fminf_(x, 1)) * (curve->table_entries - 1);
244 if (curve->table_8) {
245 l = curve->table_8[lo] * (1/255.0f);
246 h = curve->table_8[hi] * (1/255.0f);
249 memcpy(&be_l, curve->table_16 + 2*lo, 2);
250 memcpy(&be_h, curve->table_16 + 2*hi, 2);
259 float skcms_MaxRoundtripError(const skcms_Curve* curve, const skcms_TransferFunction* inv_tf) {
260 uint32_t N = curve->table_entries > 256 ? curve->table_entries : 256;
265 y = eval_curve(curve, x);
271 bool skcms_AreApproximateInverses(const skcms_Curve* curve, const skcms_TransferFunction* inv_tf) {
272 return skcms_MaxRoundtripError(curve, inv_tf) < (1/512.0f);
447 skcms_Curve* curve, uint32_t* curve_size) {
469 curve->table_entries = 0;
470 curve->parametric.a = 1.0f;
471 curve->parametric.b = 0.0f;
472 curve->parametric.c = 0.0f;
473 curve->parametric.d = 0.0f;
474 curve->parametric.e = 0.0f;
475 curve->parametric.f = 0.0f;
476 curve->parametric.g = read_big_fixed(paraTag->variable);
480 curve->parametric.a = read_big_fixed(paraTag->variable + 4);
481 curve->parametric.b = read_big_fixed(paraTag->variable + 8);
482 if (curve->parametric.a == 0) {
485 curve->parametric.d = -curve->parametric.b / curve->parametric.a;
488 curve->parametric.a = read_big_fixed(paraTag->variable + 4);
489 curve->parametric.b = read_big_fixed(paraTag->variable + 8);
490 curve->parametric.e = read_big_fixed(paraTag->variable + 12);
491 if (curve->parametric.a == 0) {
494 curve->parametric.d = -curve->parametric.b / curve->parametric.a;
495 curve->parametric.f = curve->parametric.e;
498 curve->parametric.a = read_big_fixed(paraTag->variable + 4);
499 curve->parametric.b = read_big_fixed(paraTag->variable + 8);
500 curve->parametric.c = read_big_fixed(paraTag->variable + 12);
501 curve->parametric.d = read_big_fixed(paraTag->variable + 16);
504 curve->parametric.a = read_big_fixed(paraTag->variable + 4);
505 curve->parametric.b = read_big_fixed(paraTag->variable + 8);
506 curve->parametric.c = read_big_fixed(paraTag->variable + 12);
507 curve->parametric.d = read_big_fixed(paraTag->variable + 16);
508 curve->parametric.e = read_big_fixed(paraTag->variable + 20);
509 curve->parametric.f = read_big_fixed(paraTag->variable + 24);
512 return skcms_TransferFunction_isSRGBish(&curve->parametric);
523 skcms_Curve* curve, uint32_t* curve_size) {
540 curve->table_entries = 0;
541 curve->parametric.a = 1.0f;
542 curve->parametric.b = 0.0f;
543 curve->parametric.c = 0.0f;
544 curve->parametric.d = 0.0f;
545 curve->parametric.e = 0.0f;
546 curve->parametric.f = 0.0f;
548 // Empty tables are a shorthand for an identity curve
549 curve->parametric.g = 1.0f;
552 curve->parametric.g = read_big_u16(curvTag->variable) * (1.0f / 256.0f);
555 curve->table_8 = nullptr;
556 curve->table_16 = curvTag->variable;
557 curve->table_entries = value_count;
564 // If curve_size is not nullptr, writes the number of bytes used by the curve in (*curve_size).
566 skcms_Curve* curve, uint32_t* curve_size) {
567 if (!buf || size < 4 || !curve) {
573 return read_curve_para(buf, size, curve, curve_size);
575 return read_curve_curv(buf, size, curve, curve_size);
1056 static int fit_linear(const skcms_Curve* curve, int N, float tol,
1075 *f = eval_curve(curve, 0);
1085 float y = eval_curve(curve, x);
1109 static void canonicalize_identity(skcms_Curve* curve) {
1110 if (curve->table_entries && curve->table_entries <= (uint32_t)INT_MAX) {
1111 int N = (int)curve->table_entries;
1114 if (N == fit_linear(curve, N, 1.0f/(2*N), &c,&d,&f)
1117 curve->table_entries = 0;
1118 curve->table_8 = nullptr;
1119 curve->table_16 = nullptr;
1120 curve->parametric = skcms_TransferFunction{1,1,0,0,0,0,0};
1910 // We need to enforce the same constraints here that we do when fitting a curve,
1914 // Just like when fitting the curve, there's really no way to rescue a < 0.
1992 const skcms_Curve* curve,
1995 const float y = eval_curve(curve, x);
2019 static bool gauss_newton_step(const skcms_Curve* curve,
2067 float resid = rg_nonlinear(x,curve,tf, dfdP);
2100 static float max_roundtrip_error_checked(const skcms_Curve* curve,
2112 return skcms_MaxRoundtripError(curve, &tf_inv_again);
2116 static bool fit_nonlinear(const skcms_Curve* curve, int L, int N, skcms_TransferFunction* tf) {
2151 float init_error = max_roundtrip_error_checked(curve, tf);
2159 if (!gauss_newton_step(curve, tf, L*dx, dx, N-L) || !fixup_tf()) {
2164 float max_error = max_roundtrip_error_checked(curve, tf);
2175 bool skcms_ApproximateCurve(const skcms_Curve* curve,
2178 if (!curve || !approx || !max_error) {
2182 if (curve->table_entries == 0) {
2187 if (curve->table_entries == 1 || curve->table_entries > (uint32_t)INT_MAX) {
2192 int N = (int)curve->table_entries;
2203 int L = fit_linear(curve, N, kTolerances[t], &tf.c, &tf.d);
2215 tf.a = (eval_curve(curve, (N-1)*dx) -
2216 eval_curve(curve, (N-2)*dx))
2218 tf.b = eval_curve(curve, (N-2)*dx)
2222 // Start by guessing a gamma-only curve through the midpoint.
2225 float mid_y = eval_curve(curve, mid_x);
2234 !fit_nonlinear(curve, L,N, &tf_inv)) {
2267 float err = skcms_MaxRoundtripError(curve, &tf_inv);
2523 static OpAndArg select_curve_op(const skcms_Curve* curve, int channel) {
2532 if (curve->table_entries == 0) {
2535 const skcms_TransferFunction& tf = curve->parametric;
2550 return OpAndArg{op.table, curve};