Coverage Report

Created: 2026-01-10 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dng_sdk/source/dng_spline.cpp
Line
Count
Source
1
/*****************************************************************************/
2
// Copyright 2006-2007 Adobe Systems Incorporated
3
// All Rights Reserved.
4
//
5
// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6
// accordance with the terms of the Adobe license agreement accompanying it.
7
/*****************************************************************************/
8
9
/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_spline.cpp#1 $ */ 
10
/* $DateTime: 2012/05/30 13:28:51 $ */
11
/* $Change: 832332 $ */
12
/* $Author: tknoll $ */
13
14
/*****************************************************************************/
15
16
#include "dng_spline.h"
17
18
#include "dng_assertions.h"
19
#include "dng_exceptions.h"
20
21
/******************************************************************************/
22
23
dng_spline_solver::dng_spline_solver ()
24
25
56
  : X ()
26
56
  , Y ()
27
56
  , S ()
28
  
29
56
  {
30
  
31
56
  }
32
33
/******************************************************************************/
34
35
dng_spline_solver::~dng_spline_solver ()
36
56
  {
37
  
38
56
  }
39
40
/******************************************************************************/
41
42
void dng_spline_solver::Reset ()
43
56
  {
44
  
45
56
  X.clear ();
46
56
  Y.clear ();
47
  
48
56
  S.clear ();
49
  
50
56
  }
51
52
/******************************************************************************/
53
54
void dng_spline_solver::Add (real64 x, real64 y)
55
217
  {
56
57
217
  X.push_back (x);
58
217
  Y.push_back (y);
59
60
217
  }
61
62
/******************************************************************************/
63
64
void dng_spline_solver::Solve ()
65
56
  {
66
67
  // This code computes the unique curve such that:
68
  //    It is C0, C1, and C2 continuous
69
  //    The second derivative is zero at the end points
70
  
71
56
  int32 count = (int32) X.size ();
72
  
73
56
  DNG_ASSERT (count >= 2, "Too few points");
74
  
75
56
  int32 start = 0;
76
56
  int32 end   = count;
77
  
78
56
  real64 A =  X [start+1] - X [start];
79
56
  real64 B = (Y [start+1] - Y [start]) / A;
80
  
81
56
  S.resize (count);
82
83
56
  S [start] = B;
84
  
85
56
  int32 j;
86
87
  // Slopes here are a weighted average of the slopes
88
  // to each of the adjcent control points.
89
90
161
  for (j = start + 2; j < end; ++j)
91
105
    {
92
93
105
    real64 C = X [j] - X [j-1];
94
105
    real64 D = (Y [j] - Y [j-1]) / C;
95
96
105
    S [j-1] = (B * C + D * A) / (A + C);
97
98
105
    A = C;
99
105
    B = D;
100
101
105
    }
102
103
56
  S [end-1] = 2.0 * B - S [end-2];
104
56
  S [start] = 2.0 * S [start] - S [start+1];
105
106
56
  if ((end - start) > 2)
107
47
    {
108
109
47
    dng_std_vector<real64> E;
110
47
    dng_std_vector<real64> F;
111
47
    dng_std_vector<real64> G;
112
    
113
47
    E.resize (count);
114
47
    F.resize (count);
115
47
    G.resize (count);
116
117
47
    F [start] = 0.5;
118
47
    E [end-1] = 0.5;
119
47
    G [start] = 0.75 * (S [start] + S [start+1]);
120
47
    G [end-1] = 0.75 * (S [end-2] + S [end-1]);
121
122
152
    for (j = start+1; j < end - 1; ++j)
123
105
      {
124
125
105
      A = (X [j+1] - X [j-1]) * 2.0;
126
127
105
      E [j] = (X [j+1] - X [j]) / A;
128
105
      F [j] = (X [j] - X [j-1]) / A;
129
105
      G [j] = 1.5 * S [j];
130
131
105
      }
132
133
199
    for (j = start+1; j < end; ++j)
134
152
      {
135
136
152
      A = 1.0 - F [j-1] * E [j];
137
138
152
      if (j != end-1) F [j] /= A;
139
140
152
      G [j] = (G [j] - G [j-1] * E [j]) / A;
141
142
152
      }
143
144
199
    for (j = end - 2; j >= start; --j)
145
152
      G [j] = G [j] - F [j] * G [j+1];
146
147
246
    for (j = start; j < end; ++j)
148
199
      S [j] = G [j];
149
150
47
    }
151
152
56
  }
153
154
/******************************************************************************/
155
156
bool dng_spline_solver::IsIdentity () const
157
0
  {
158
  
159
0
  int32 count = (int32) X.size ();
160
  
161
0
  if (count != 2)
162
0
    return false;
163
    
164
0
  if (X [0] != 0.0 || X [1] != 1.0 ||
165
0
    Y [0] != 0.0 || Y [1] != 1.0)
166
0
    return false;
167
    
168
0
  return true;
169
  
170
0
  }
171
172
/******************************************************************************/
173
174
real64 dng_spline_solver::Evaluate (real64 x) const
175
217k
  {
176
177
217k
  int32 count = (int32) X.size ();
178
  
179
  // Check for off each end of point list.
180
  
181
217k
  if (x <= X [0])
182
3.66k
    return Y [0];
183
184
213k
  if (x >= X [count-1])
185
158k
    return Y [count-1];
186
187
  // Binary search for the index.
188
  
189
55.2k
  int32 lower = 1;
190
55.2k
  int32 upper = count - 1;
191
  
192
94.2k
  while (upper > lower)
193
39.0k
    {
194
    
195
39.0k
    int32 mid = (lower + upper) >> 1;
196
    
197
39.0k
    if (x == X [mid])
198
22
      {
199
22
      return Y [mid];
200
22
      }
201
      
202
38.9k
    if (x > X [mid])
203
9.47k
      lower = mid + 1;
204
29.5k
    else
205
29.5k
      upper = mid;
206
    
207
38.9k
    }
208
    
209
55.2k
  DNG_ASSERT (upper == lower, "Binary search error in point list");
210
211
55.2k
  int32 j = lower;
212
    
213
  // X [j - 1] < x <= X [j]
214
  // A is the distance between the X [j] and X [j - 1]
215
  // B and C describe the fractional distance to either side. B + C = 1.
216
217
  // We compute a cubic spline between the two points with slopes
218
  // S[j-1] and S[j] at either end. Specifically, we compute the 1-D Bezier
219
  // with control values:
220
  //
221
  //    Y[j-1], Y[j-1] + S[j-1]*A, Y[j]-S[j]*A, Y[j]
222
  
223
55.2k
  return EvaluateSplineSegment (x,
224
55.2k
                  X [j - 1],
225
55.2k
                  Y [j - 1],
226
55.2k
                  S [j - 1],
227
55.2k
                  X [j    ],
228
55.2k
                  Y [j    ],
229
55.2k
                  S [j    ]);
230
231
55.2k
  }
232
    
233
/*****************************************************************************/