Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
curve_tools.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2011-2022 darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17
18 Part of this file is based on nikon_curve.c from UFraw
19 Copyright 2004-2008 by Shawn Freeman, Udi Fuchs
20*/
21
22#include "curve_tools.h"
23
24#include <float.h>
25#include <math.h>
26#include <stdio.h>
27#include <stdlib.h>
28
29#define EPSILON 2 * FLT_MIN
30#define MAX_ITER 10
31
32static const int curvedata_anchors_max = 20;
33
34// declare some functions and so I can use the function pointer
35float spline_cubic_val(int n, float t[], float tval, float y[], float ypp[]);
36float catmull_rom_val(int n, float x[], float xval, float y[], float tangents[]);
37
38float *spline_cubic_set(int n, float t[], float y[]);
39float *catmull_rom_set(int n, float x[], float y[]);
40float *monotone_hermite_set(int n, float x[], float y[]);
41
42float (*spline_val[])(int, float[], float, float[], float[])
44
45float *(*spline_set[])(int, float[], float[]) = { spline_cubic_set, catmull_rom_set, monotone_hermite_set };
46
47/**********************************************************************
48
49 Purpose:
50
51 D3_NP_FS factors and solves a D3 system.
52
53 Discussion:
54
55 The D3 storage format is used for a tridiagonal matrix.
56 The superdiagonal is stored in entries (1,2:N), the diagonal in
57 entries (2,1:N), and the subdiagonal in (3,1:N-1). Thus, the
58 original matrix is "collapsed" vertically into the array.
59
60 This algorithm requires that each diagonal entry be nonzero.
61 It does not use pivoting, and so can fail on systems that
62 are actually nonsingular.
63
64 Example:
65
66 Here is how a D3 matrix of order 5 would be stored:
67
68 * A12 A23 A34 A45
69 A11 A22 A33 A44 A55
70 A21 A32 A43 A54 *
71
72 Modified:
73
74 07 January 2005 Shawn Freeman (pure C modifications)
75 15 November 2003 John Burkardt
76
77 Author:
78
79 John Burkardt
80
81 Parameters:
82
83 Input, int N, the order of the linear system.
84
85 Input/output, float A[3*N].
86 On input, the nonzero diagonals of the linear system.
87 On output, the data in these vectors has been overwritten
88 by factorization information.
89
90 Input, float B[N], the right hand side.
91
92 Output, float D3_NP_FS[N], the solution of the linear system.
93 This is NULL if there was an error because one of the diagonal
94 entries was zero.
95**********************************************************************/
96float *d3_np_fs(int n, float a[], float b[])
97
98{
99 if(n <= 0 || n > curvedata_anchors_max) return NULL;
100
101 //
102 // Check.
103 //
104 for(int i = 0; i < n; i++)
105 {
106 if(a[1 + i * 3] == 0.0E+00)
107 {
108 return NULL;
109 }
110 }
111 float *x = (float *)calloc(n, sizeof(float));
112 // nc_merror(x, "d3_np_fs");
113
114 for(int i = 0; i < n; i++)
115 {
116 x[i] = b[i];
117 }
118
119 for(int i = 1; i < n; i++)
120 {
121 const float xmult = a[2 + (i - 1) * 3] / a[1 + (i - 1) * 3];
122 a[1 + i * 3] = a[1 + i * 3] - xmult * a[0 + i * 3];
123 x[i] = x[i] - xmult * x[i - 1];
124 }
125
126 x[n - 1] = x[n - 1] / a[1 + (n - 1) * 3];
127 for(int i = n - 2; 0 <= i; i--)
128 {
129 x[i] = (x[i] - a[0 + (i + 1) * 3] * x[i + 1]) / a[1 + i * 3];
130 }
131
132 return x;
133}
134
135/**********************************************************************
136
137 Purpose:
138
139 SPLINE_CUBIC_SET computes the second derivatives of a piecewise cubic spline.
140
141 Discussion:
142
143 For data interpolation, the user must call SPLINE_SET to determine
144 the second derivative data, passing in the data to be interpolated,
145 and the desired boundary conditions.
146
147 The data to be interpolated, plus the SPLINE_SET output, defines
148 the spline. The user may then call SPLINE_VAL to evaluate the
149 spline at any point.
150
151 The cubic spline is a piecewise cubic polynomial. The intervals
152 are determined by the "knots" or abscissas of the data to be
153 interpolated. The cubic spline has continuous first and second
154 derivatives over the entire interval of interpolation.
155
156 For any point T in the interval T(IVAL), T(IVAL+1), the form of
157 the spline is
158
159 SPL(T) = A(IVAL)
160 + B(IVAL) * ( T - T(IVAL) )
161 + C(IVAL) * ( T - T(IVAL) )**2
162 + D(IVAL) * ( T - T(IVAL) )**3
163
164 If we assume that we know the values Y(*) and YPP(*), which represent
165 the values and second derivatives of the spline at each knot, then
166 the coefficients can be computed as:
167
168 A(IVAL) = Y(IVAL)
169 B(IVAL) = ( Y(IVAL+1) - Y(IVAL) ) / ( T(IVAL+1) - T(IVAL) )
170 - ( YPP(IVAL+1) + 2 * YPP(IVAL) ) * ( T(IVAL+1) - T(IVAL) ) / 6
171 C(IVAL) = YPP(IVAL) / 2
172 D(IVAL) = ( YPP(IVAL+1) - YPP(IVAL) ) / ( 6 * ( T(IVAL+1) - T(IVAL) ) )
173
174 Since the first derivative of the spline is
175
176 SPL'(T) = B(IVAL)
177 + 2 * C(IVAL) * ( T - T(IVAL) )
178 + 3 * D(IVAL) * ( T - T(IVAL) )**2,
179
180 the requirement that the first derivative be continuous at interior
181 knot I results in a total of N-2 equations, of the form:
182
183 B(IVAL-1) + 2 C(IVAL-1) * (T(IVAL)-T(IVAL-1))
184 + 3 * D(IVAL-1) * (T(IVAL) - T(IVAL-1))**2 = B(IVAL)
185
186 or, setting H(IVAL) = T(IVAL+1) - T(IVAL)
187
188 ( Y(IVAL) - Y(IVAL-1) ) / H(IVAL-1)
189 - ( YPP(IVAL) + 2 * YPP(IVAL-1) ) * H(IVAL-1) / 6
190 + YPP(IVAL-1) * H(IVAL-1)
191 + ( YPP(IVAL) - YPP(IVAL-1) ) * H(IVAL-1) / 2
192 =
193 ( Y(IVAL+1) - Y(IVAL) ) / H(IVAL)
194 - ( YPP(IVAL+1) + 2 * YPP(IVAL) ) * H(IVAL) / 6
195
196 or
197
198 YPP(IVAL-1) * H(IVAL-1) + 2 * YPP(IVAL) * ( H(IVAL-1) + H(IVAL) )
199 + YPP(IVAL) * H(IVAL)
200 =
201 6 * ( Y(IVAL+1) - Y(IVAL) ) / H(IVAL)
202 - 6 * ( Y(IVAL) - Y(IVAL-1) ) / H(IVAL-1)
203
204 Boundary conditions must be applied at the first and last knots.
205 The resulting tridiagonal system can be solved for the YPP values.
206
207 Modified:
208
209 07 January 2005 Shawn Freeman (pure C modifications)
210 06 February 2004 John Burkardt
211
212
213 Author:
214
215 John Burkardt
216
217 Parameters:
218
219 Input, int N, the number of data points. N must be at least 2.
220 In the special case where N = 2 and IBCBEG = IBCEND = 0, the
221 spline will actually be linear.
222
223 Input, float T[N], the knot values, that is, the points were data is
224 specified. The knot values should be distinct, and increasing.
225
226 Input, float Y[N], the data values to be interpolated.
227
228 Input, int IBCBEG, left boundary condition flag:
229 0: the cubic spline should be a quadratic over the first interval;
230 1: the first derivative at the left endpoint should be YBCBEG;
231 2: the second derivative at the left endpoint should be YBCBEG.
232
233 Input, float YBCBEG, the values to be used in the boundary
234 conditions if IBCBEG is equal to 1 or 2.
235
236 Input, int IBCEND, right boundary condition flag:
237 0: the cubic spline should be a quadratic over the last interval;
238 1: the first derivative at the right endpoint should be YBCEND;
239 2: the second derivative at the right endpoint should be YBCEND.
240
241 Input, float YBCEND, the values to be used in the boundary
242 conditions if IBCEND is equal to 1 or 2.
243
244 Output, float SPLINE_CUBIC_SET[N], the second derivatives of the cubic spline.
245**********************************************************************/
246static float *spline_cubic_set_internal(int n, float t[], float y[], int ibcbeg, float ybcbeg, int ibcend,
247 float ybcend)
248{
249 //
250 // Check.
251 //
252 if(n <= 1)
253 {
254 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
255 // "The number of data points must be at least 2.\n");
256 return NULL;
257 }
258
259 for(int i = 0; i < n - 1; i++)
260 {
261 if(t[i + 1] <= t[i])
262 {
263 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
264 // "The knots must be strictly increasing, but "
265 // "T(%u) = %e, T(%u) = %e\n",i,t[i],i+1,t[i+1]);
266 return NULL;
267 }
268 }
269 float *a = (float *)calloc(3 * n, sizeof(float));
270 // nc_merror(a, "spline_cubic_set");
271 float *b = (float *)calloc(n, sizeof(float));
272 // nc_merror(b, "spline_cubic_set");
273 //
274 // Set up the first equation.
275 //
276 if(ibcbeg == 0)
277 {
278 b[0] = 0.0E+00;
279 a[1 + 0 * 3] = 1.0E+00;
280 a[0 + 1 * 3] = -1.0E+00;
281 }
282 else if(ibcbeg == 1)
283 {
284 b[0] = (y[1] - y[0]) / (t[1] - t[0]) - ybcbeg;
285 a[1 + 0 * 3] = (t[1] - t[0]) / 3.0E+00;
286 a[0 + 1 * 3] = (t[1] - t[0]) / 6.0E+00;
287 }
288 else if(ibcbeg == 2)
289 {
290 b[0] = ybcbeg;
291 a[1 + 0 * 3] = 1.0E+00;
292 a[0 + 1 * 3] = 0.0E+00;
293 }
294 else
295 {
296 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
297 // "IBCBEG must be 0, 1 or 2. The input value is %u.\n", ibcbeg);
298 free(a);
299 free(b);
300 return NULL;
301 }
302 //
303 // Set up the intermediate equations.
304 //
305 for(int i = 1; i < n - 1; i++)
306 {
307 b[i] = (y[i + 1] - y[i]) / (t[i + 1] - t[i]) - (y[i] - y[i - 1]) / (t[i] - t[i - 1]);
308 a[2 + (i - 1) * 3] = (t[i] - t[i - 1]) / 6.0E+00;
309 a[1 + i * 3] = (t[i + 1] - t[i - 1]) / 3.0E+00;
310 a[0 + (i + 1) * 3] = (t[i + 1] - t[i]) / 6.0E+00;
311 }
312 //
313 // Set up the last equation.
314 //
315 if(ibcend == 0)
316 {
317 b[n - 1] = 0.0E+00;
318 a[2 + (n - 2) * 3] = -1.0E+00;
319 a[1 + (n - 1) * 3] = 1.0E+00;
320 }
321 else if(ibcend == 1)
322 {
323 b[n - 1] = ybcend - (y[n - 1] - y[n - 2]) / (t[n - 1] - t[n - 2]);
324 a[2 + (n - 2) * 3] = (t[n - 1] - t[n - 2]) / 6.0E+00;
325 a[1 + (n - 1) * 3] = (t[n - 1] - t[n - 2]) / 3.0E+00;
326 }
327 else if(ibcend == 2)
328 {
329 b[n - 1] = ybcend;
330 a[2 + (n - 2) * 3] = 0.0E+00;
331 a[1 + (n - 1) * 3] = 1.0E+00;
332 }
333 else
334 {
335 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
336 // "IBCEND must be 0, 1 or 2. The input value is %u", ibcend);
337 free(a);
338 free(b);
339 return NULL;
340 }
341 //
342 // Solve the linear system.
343 //
344 float *ypp = NULL;
345
346 if(n == 2 && ibcbeg == 0 && ibcend == 0)
347 {
348 ypp = (float *)calloc(2, sizeof(float));
349 // nc_merror(ypp, "spline_cubic_set");
350
351 ypp[0] = 0.0E+00;
352 ypp[1] = 0.0E+00;
353 }
354 else
355 {
356 ypp = d3_np_fs(n, a, b);
357
358 if(!ypp)
359 {
360 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
361 // "The linear system could not be solved.\n");
362 free(a);
363 free(b);
364 return NULL;
365 }
366 }
367
368 free(a);
369 free(b);
370 return ypp;
371}
372/************************************************************
373 *
374 * This is a convenience wrapper function around spline_cubic_set
375 *
376 ************************************************************/
377float *spline_cubic_set(int n, float t[], float y[])
378{
379 return spline_cubic_set_internal(n, t, y, 2, 0.0, 2, 0.0);
380}
381
382/*************************************************************
383* monotone_hermite_set:
384* calculates the tangents for a monotonic hermite spline curve.
385* see http://en.wikipedia.org/wiki/Monotone_cubic_interpolation
386*
387* input:
388* n = number of control points
389* x = input x array
390* y = input y array
391* output:
392* pointer to array containing the tangents
393*************************************************************/
394float *monotone_hermite_set(int n, float x[], float y[])
395{
396 if(n <= 1)
397 {
398 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
399 // "The number of data points must be at least 2.\n");
400 return NULL;
401 }
402
403 for(int i = 0; i < n - 1; i++)
404 {
405 if(x[i + 1] <= x[i])
406 {
407 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
408 // "The knots must be strictly increasing, but "
409 // "T(%u) = %e, T(%u) = %e\n",i,x[i],i+1,x[i+1]);
410 return NULL;
411 }
412 }
413
414 float *delta = (float *)calloc(n, sizeof(float));
415 // nc_merror(delta, "spline_cubic_set");
416 float *m = (float *)calloc(n + 1, sizeof(float));
417 // nc_merror(m, "spline_cubic_set");
418 // calculate the slopes
419 for(int i = 0; i < n - 1; i++)
420 {
421 delta[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]);
422 }
423 delta[n - 1] = delta[n - 2];
424
425 m[0] = delta[0];
426 m[n - 1] = delta[n - 1];
427
428 for(int i = 1; i < n - 1; i++)
429 {
430 m[i] = (delta[i - 1] + delta[i]) * .5f;
431 }
432 for(int i = 0; i < n; i++)
433 {
434 if(fabsf(delta[i]) < EPSILON)
435 {
436 m[i] = 0.0f;
437 m[i + 1] = 0.0f;
438 }
439 else
440 {
441 const float alpha = m[i] / delta[i];
442 const float beta = m[i + 1] / delta[i];
443 const float tau = alpha * alpha + beta * beta;
444 if(tau > 9.0f)
445 {
446 m[i] = 3.0f * alpha * delta[i] / sqrtf(tau);
447 m[i + 1] = 3.0f * beta * delta[i] / sqrtf(tau);
448 }
449 }
450 }
451 free(delta);
452 return m;
453}
454
455/*************************************************************
456* catmull_rom_set:
457* calculates the tangents for a catmull_rom spline
458* see http://en.wikipedia.org/wiki/Cubic_Hermite_spline
459*
460*
461* input:
462* n = number of control points
463* x = input x array
464* y = input y array
465* output:
466* pointer to array containing the tangents
467*************************************************************/
468float *catmull_rom_set(int n, float x[], float y[])
469{
470 if(n <= 1)
471 {
472 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
473 // "The number of data points must be at least 2.\n");
474 return NULL;
475 }
476
477 for(int i = 0; i < n - 1; i++)
478 {
479 if(x[i + 1] <= x[i])
480 {
481 // nc_message(NC_SET_ERROR, "spline_cubic_set() error: "
482 // "The knots must be strictly increasing, but "
483 // "T(%u) = %e, T(%u) = %e\n",i,x[i],i+1,x[i+1]);
484 return NULL;
485 }
486 }
487 // nc_merror(delta, "spline_cubic_set");
488 float *m = (float *)calloc(n, sizeof(float));
489 // nc_merror(m, "spline_cubic_set");
490
491 // calculate the slopes
492 m[0] = (y[1] - y[0]) / (x[1] - x[0]);
493 for(int i = 1; i < n - 1; i++)
494 {
495 m[i] = (y[i + 1] - y[i - 1]) / (x[i + 1] - x[i - 1]);
496 }
497 m[n - 1] = (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]);
498
499 return m;
500}
501
502float *interpolate_set(int n, float x[], float y[], unsigned int type)
503{
504 return (*spline_set[type])(n, x, y);
505}
506
507float interpolate_val(int n, float x[], float xval, float y[], float tangents[], unsigned int type)
508{
509 return (*spline_val[type])(n, x, xval, y, tangents);
510}
511
512/*************************************************************
513 * catmull_rom_val:
514 * piecewise catmull-rom interpolation
515 *
516 * n = number of control points
517 * x = input x array
518 * xval = input value where to interpolate the data
519 * y = input y array
520 * tangent = input array of tangents
521 * output:
522 * interpolated value at xval
523 *
524 *************************************************************/
525float catmull_rom_val(int n, float x[], float xval, float y[], float tangents[])
526{
527 //
528 // Determine the interval [ T(I), T(I+1) ] that contains TVAL.
529 // Values below T[0] or above T[N-1] use extrapolation.
530 //
531 int ival = n - 2;
532
533 for(int i = 0; i < n - 2; i++)
534 {
535 if(xval < x[i + 1])
536 {
537 ival = i;
538 break;
539 }
540 }
541
542 const float m0 = tangents[ival];
543 const float m1 = tangents[ival + 1];
544 //
545 // In the interval I, the polynomial is in terms of a normalized
546 // coordinate between 0 and 1.
547 //
548 const float h = x[ival + 1] - x[ival];
549 const float dx = (xval - x[ival]) / h;
550 const float dx2 = dx * dx;
551 const float dx3 = dx * dx2;
552
553 const float h00 = (2.0 * dx3) - (3.0 * dx2) + 1.0;
554 const float h10 = (1.0 * dx3) - (2.0 * dx2) + dx;
555 const float h01 = (-2.0 * dx3) + (3.0 * dx2);
556 const float h11 = (1.0 * dx3) - (1.0 * dx2);
557
558 return (h00 * y[ival]) + (h10 * h * m0) + (h01 * y[ival + 1]) + (h11 * h * m1);
559}
560
561
562/**********************************************************************
563
564 Purpose:
565
566 SPLINE_CUBIC_VAL evaluates a piecewise cubic spline at a point.
567
568 Discussion:
569
570 SPLINE_CUBIC_SET must have already been called to define the values of YPP.
571
572 For any point T in the interval T(IVAL), T(IVAL+1), the form of
573 the spline is
574
575 SPL(T) = A
576 + B * ( T - T(IVAL) )
577 + C * ( T - T(IVAL) )**2
578 + D * ( T - T(IVAL) )**3
579
580 Here:
581 A = Y(IVAL)
582 B = ( Y(IVAL+1) - Y(IVAL) ) / ( T(IVAL+1) - T(IVAL) )
583 - ( YPP(IVAL+1) + 2 * YPP(IVAL) ) * ( T(IVAL+1) - T(IVAL) ) / 6
584 C = YPP(IVAL) / 2
585 D = ( YPP(IVAL+1) - YPP(IVAL) ) / ( 6 * ( T(IVAL+1) - T(IVAL) ) )
586
587 Modified:
588
589 07 January 2005 Shawn Freeman (pure C modifications)
590 04 February 1999 John Burkardt
591
592 Author:
593
594 John Burkardt
595
596 Parameters:
597
598 Input, int n, the number of knots.
599
600 Input, float Y[N], the data values at the knots.
601
602 Input, float T[N], the knot values.
603
604 Input, float TVAL, a point, typically between T[0] and T[N-1], at
605 which the spline is to be evalulated. If TVAL lies outside
606 this range, extrapolation is used.
607
608 Input, float Y[N], the data values at the knots.
609
610 Input, float YPP[N], the second derivatives of the spline at
611 the knots.
612
613
614 Output, float SPLINE_VAL, the value of the spline at TVAL.
615
616**********************************************************************/
617float spline_cubic_val(int n, float t[], float tval, float y[], float ypp[])
618{
619 int ival = 0;
620 //
621 // Determine the interval [ T(I), T(I+1) ] that contains TVAL.
622 // Values below T[0] or above T[N-1] use extrapolation.
623 //
624 ival = n - 2;
625
626 for(int i = 0; i < n - 1; i++)
627 {
628 if(tval < t[i + 1])
629 {
630 ival = i;
631 break;
632 }
633 }
634 //
635 // In the interval I, the polynomial is in terms of a normalized
636 // coordinate between 0 and 1.
637 //
638 const float dt = tval - t[ival];
639 const float h = t[ival + 1] - t[ival];
640
641 const float yval = y[ival]
642 + dt * ((y[ival + 1] - y[ival]) / h - (ypp[ival + 1] / 6.0E+00 + ypp[ival] / 3.0E+00) * h
643 + dt * (0.5E+00 * ypp[ival] + dt * ((ypp[ival + 1] - ypp[ival]) / (6.0E+00 * h))));
644
645 // we really never need the derivatives so commented this out
653 return yval;
654}
655
656
657/*********************************************
658CurveDataSample:
659 Samples from a spline curve constructed from
660 the Nikon data.
661
662 curve - Pointer to curve struct to hold the data.
663 sample - Pointer to sample struct to hold the data.
664**********************************************/
666{
667 int n = 0;
668
669 float x[20] = { 0 };
670 float y[20] = { 0 };
671
672 // The box points are what the anchor points are relative
673 // to so...
674
675 const float box_width = curve->m_max_x - curve->m_min_x;
676 const float box_height = curve->m_max_y - curve->m_min_y;
677
678 // build arrays for processing
679 if(curve->m_numAnchors == 0)
680 {
681 // just a straight line using box coordinates
682 x[0] = curve->m_min_x;
683 y[0] = curve->m_min_y;
684 x[1] = curve->m_max_x;
685 y[1] = curve->m_max_y;
686 n = 2;
687 }
688 else
689 {
690 for(int i = 0; i < curve->m_numAnchors; i++)
691 {
692 x[i] = curve->m_anchors[i].x * box_width + curve->m_min_x;
693 y[i] = curve->m_anchors[i].y * box_height + curve->m_min_y;
694 }
695 n = curve->m_numAnchors;
696 }
697 const float res = 1.0 / (float)(sample->m_samplingRes - 1);
698 const int firstPointX = x[0] * (sample->m_samplingRes - 1);
699 const int firstPointY = y[0] * (sample->m_outputRes - 1);
700 const int lastPointX = x[n - 1] * (sample->m_samplingRes - 1);
701 const int lastPointY = y[n - 1] * (sample->m_outputRes - 1);
702 const int maxY = curve->m_max_y * (sample->m_outputRes - 1);
703 const int minY = curve->m_min_y * (sample->m_outputRes - 1);
704 // returns an array of second derivatives used to calculate the spline curve.
705 // this is a malloc'd array that needs to be freed when done.
706 // The settings currently calculate the natural spline, which closely matches
707 // camera curve output in raw files.
708 float *ypp = interpolate_set(n, x, y, curve->m_spline_type);
709 if(ypp == NULL) return CT_ERROR;
710
711 for(int i = 0; i < (int)sample->m_samplingRes; i++)
712 {
713 // get the value of the curve at a point
714 // take into account that curves may not necessarily begin at x = 0.0
715 // nor end at x = 1.0
716
717 // Before the first point and after the last point, take a strait line
718 if(i < firstPointX)
719 {
720 sample->m_Samples[i] = firstPointY;
721 }
722 else if(i > lastPointX)
723 {
724 sample->m_Samples[i] = lastPointY;
725 }
726 else
727 {
728 // within range, we can sample the curve
729 int val = interpolate_val(n, x, i * res, y, ypp, curve->m_spline_type) * (sample->m_outputRes - 1) + 0.5;
730 if(val > maxY) val = maxY;
731 if(val < minY) val = minY;
732 sample->m_Samples[i] = val;
733 }
734 }
735
736 free(ypp);
737 return CT_SUCCESS;
738}
739
740// clang-format off
741// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
742// vim: shiftwidth=2 expandtab tabstop=2 cindent
743// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
744// clang-format on
745
#define m
Definition basecurve.c:231
int type
Definition common/metadata.c:42
#define EPSILON
Definition curve_tools.c:29
float * interpolate_set(int n, float x[], float y[], unsigned int type)
Definition curve_tools.c:502
float catmull_rom_val(int n, float x[], float xval, float y[], float tangents[])
Definition curve_tools.c:525
float * catmull_rom_set(int n, float x[], float y[])
Definition curve_tools.c:468
float(* spline_val[])(int, float[], float, float[], float[])
Definition curve_tools.c:42
float * monotone_hermite_set(int n, float x[], float y[])
Definition curve_tools.c:394
int CurveDataSample(CurveData *curve, CurveSample *sample)
Definition curve_tools.c:665
static float * spline_cubic_set_internal(int n, float t[], float y[], int ibcbeg, float ybcbeg, int ibcend, float ybcend)
Definition curve_tools.c:246
static const int curvedata_anchors_max
Definition curve_tools.c:32
float * spline_cubic_set(int n, float t[], float y[])
Definition curve_tools.c:377
float *(* spline_set[])(int, float[], float[])
Definition curve_tools.c:45
float interpolate_val(int n, float x[], float xval, float y[], float tangents[], unsigned int type)
Definition curve_tools.c:507
float spline_cubic_val(int n, float t[], float tval, float y[], float ypp[])
Definition curve_tools.c:617
float * d3_np_fs(int n, float a[], float b[])
Definition curve_tools.c:96
#define CT_ERROR
Definition curve_tools.h:35
#define CT_SUCCESS
Definition curve_tools.h:34
float x
Definition curve_tools.h:51
float y
Definition curve_tools.h:52
Definition curve_tools.h:56
CurveAnchorPoint m_anchors[20]
Definition curve_tools.h:71
float m_min_x
Definition curve_tools.h:61
float m_max_x
Definition curve_tools.h:62
unsigned char m_numAnchors
Definition curve_tools.h:67
unsigned int m_spline_type
Definition curve_tools.h:58
float m_max_y
Definition curve_tools.h:64
float m_min_y
Definition curve_tools.h:63
Definition curve_tools.h:76
unsigned int m_outputRes
Definition curve_tools.h:79
unsigned int m_samplingRes
Definition curve_tools.h:78
unsigned short int * m_Samples
Definition curve_tools.h:82