Coverage Report

Created: 2025-07-01 06:34

/src/lcms/src/cmsintrp.c
Line
Count
Source (jump to first uncovered line)
1
//---------------------------------------------------------------------------------
2
//
3
//  Little Color Management System
4
//  Copyright (c) 1998-2024 Marti Maria Saguer
5
//
6
// Permission is hereby granted, free of charge, to any person obtaining
7
// a copy of this software and associated documentation files (the "Software"),
8
// to deal in the Software without restriction, including without limitation
9
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
// and/or sell copies of the Software, and to permit persons to whom the Software
11
// is furnished to do so, subject to the following conditions:
12
//
13
// The above copyright notice and this permission notice shall be included in
14
// all copies or substantial portions of the Software.
15
//
16
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
//
24
//---------------------------------------------------------------------------------
25
//
26
27
#include "lcms2_internal.h"
28
29
// This module incorporates several interpolation routines, for 1 to 8 channels on input and
30
// up to 65535 channels on output. The user may change those by using the interpolation plug-in
31
32
// Some people may want to compile as C++ with all warnings on, in this case make compiler silent
33
#ifdef _MSC_VER
34
#    if (_MSC_VER >= 1400)
35
#       pragma warning( disable : 4365 )
36
#    endif
37
#endif
38
39
// Interpolation routines by default
40
static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
41
42
// This is the default factory
43
_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL };
44
45
// The interpolation plug-in memory chunk allocator/dup
46
void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
47
0
{
48
0
    void* from;
49
50
0
    _cmsAssert(ctx != NULL);
51
52
0
    if (src != NULL) {
53
0
        from = src ->chunks[InterpPlugin];       
54
0
    }
55
0
    else { 
56
0
        static _cmsInterpPluginChunkType InterpPluginChunk = { NULL };
57
58
0
        from = &InterpPluginChunk;
59
0
    }
60
61
0
    _cmsAssert(from != NULL);
62
0
    ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType));
63
0
}
64
65
66
// Main plug-in entry
67
cmsBool  _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data)
68
0
{
69
0
    cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
70
0
    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
71
72
0
    if (Data == NULL) {
73
74
0
        ptr ->Interpolators = NULL;
75
0
        return TRUE;
76
0
    }
77
78
    // Set replacement functions
79
0
    ptr ->Interpolators = Plugin ->InterpolatorsFactory;
80
0
    return TRUE;
81
0
}
82
83
84
// Set the interpolation method
85
cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p)
86
70.1k
{      
87
70.1k
    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
88
89
70.1k
    p ->Interpolation.Lerp16 = NULL;
90
91
   // Invoke factory, possibly in the Plug-in
92
70.1k
    if (ptr ->Interpolators != NULL)
93
0
        p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
94
    
95
    // If unsupported by the plug-in, go for the LittleCMS default.
96
    // If happens only if an extern plug-in is being used
97
70.1k
    if (p ->Interpolation.Lerp16 == NULL)
98
70.1k
        p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
99
100
    // Check for valid interpolator (we just check one member of the union)
101
70.1k
    if (p ->Interpolation.Lerp16 == NULL) {
102
0
            return FALSE;
103
0
    }
104
105
70.1k
    return TRUE;
106
70.1k
}
107
108
109
// This function precalculates as many parameters as possible to speed up the interpolation.
110
cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
111
                                           const cmsUInt32Number nSamples[],
112
                                           cmsUInt32Number InputChan, cmsUInt32Number OutputChan,
113
                                           const void *Table,
114
                                           cmsUInt32Number dwFlags)
115
68.8k
{
116
68.8k
    cmsInterpParams* p;
117
68.8k
    cmsUInt32Number i;
118
119
    // Check for maximum inputs
120
68.8k
    if (InputChan > MAX_INPUT_DIMENSIONS) {
121
0
             cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
122
0
            return NULL;
123
0
    }
124
125
    // Creates an empty object
126
68.8k
    p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
127
68.8k
    if (p == NULL) return NULL;
128
129
    // Keep original parameters
130
68.8k
    p -> dwFlags  = dwFlags;
131
68.8k
    p -> nInputs  = InputChan;
132
68.8k
    p -> nOutputs = OutputChan;
133
68.8k
    p ->Table     = Table;
134
68.8k
    p ->ContextID  = ContextID;
135
136
    // Fill samples per input direction and domain (which is number of nodes minus one)
137
159k
    for (i=0; i < InputChan; i++) {
138
139
90.3k
        p -> nSamples[i] = nSamples[i];
140
90.3k
        p -> Domain[i]   = nSamples[i] - 1;
141
90.3k
    }
142
143
    // Compute factors to apply to each component to index the grid array
144
68.8k
    p -> opta[0] = p -> nOutputs;
145
90.3k
    for (i=1; i < InputChan; i++)
146
21.4k
        p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
147
148
149
68.8k
    if (!_cmsSetInterpolationRoutine(ContextID, p)) {
150
0
         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
151
0
        _cmsFree(ContextID, p);
152
0
        return NULL;
153
0
    }
154
155
    // All seems ok
156
68.8k
    return p;
157
68.8k
}
158
159
160
// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
161
cmsInterpParams* CMSEXPORT _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples, 
162
                                                   cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags)
163
59.7k
{
164
59.7k
    int i;
165
59.7k
    cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
166
167
    // Fill the auxiliary array
168
955k
    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
169
895k
        Samples[i] = nSamples;
170
171
    // Call the extended function
172
59.7k
    return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
173
59.7k
}
174
175
176
// Free all associated memory
177
void CMSEXPORT _cmsFreeInterpParams(cmsInterpParams* p)
178
69.0k
{
179
69.0k
    if (p != NULL) _cmsFree(p ->ContextID, p);
180
69.0k
}
181
182
183
// Inline fixed point interpolation
184
cmsINLINE CMS_NO_SANITIZE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
185
581M
{
186
581M
    cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
187
581M
    dif = (dif >> 16) + l;
188
581M
    return (cmsUInt16Number) (dif);
189
581M
}
190
191
192
//  Linear interpolation (Fixed-point optimized)
193
static
194
void LinLerp1D(CMSREGISTER const cmsUInt16Number Value[],
195
               CMSREGISTER cmsUInt16Number Output[],
196
               CMSREGISTER const cmsInterpParams* p)
197
95.3M
{
198
95.3M
    cmsUInt16Number y1, y0;
199
95.3M
    int cell0, rest;
200
95.3M
    int val3;
201
95.3M
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
202
203
    // if last value or just one point
204
95.3M
    if (Value[0] == 0xffff || p->Domain[0] == 0) {
205
206
20.0M
        Output[0] = LutTable[p -> Domain[0]];      
207
20.0M
    }
208
75.3M
    else
209
75.3M
    {
210
75.3M
        val3 = p->Domain[0] * Value[0];
211
75.3M
        val3 = _cmsToFixedDomain(val3);    // To fixed 15.16
212
213
75.3M
        cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
214
75.3M
        rest = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
215
216
75.3M
        y0 = LutTable[cell0];
217
75.3M
        y1 = LutTable[cell0 + 1];
218
219
75.3M
        Output[0] = LinearInterp(rest, y0, y1);
220
75.3M
    }
221
95.3M
}
222
223
// To prevent out of bounds indexing
224
cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v) 
225
115k
{
226
115k
    return ((v < 1.0e-9f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v);
227
115k
}
228
229
// Floating-point version of 1D interpolation
230
static
231
void LinLerp1Dfloat(const cmsFloat32Number Value[],
232
                    cmsFloat32Number Output[],
233
                    const cmsInterpParams* p)
234
115k
{
235
115k
       cmsFloat32Number y1, y0;
236
115k
       cmsFloat32Number val2, rest;
237
115k
       int cell0, cell1;
238
115k
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
239
240
115k
       val2 = fclamp(Value[0]);
241
242
       // if last value...
243
115k
       if (val2 == 1.0 || p->Domain[0] == 0) {
244
62.1k
           Output[0] = LutTable[p -> Domain[0]];          
245
62.1k
       }
246
53.0k
       else
247
53.0k
       {
248
53.0k
           val2 *= p->Domain[0];
249
250
53.0k
           cell0 = (int)floor(val2);
251
53.0k
           cell1 = (int)ceil(val2);
252
253
           // Rest is 16 LSB bits
254
53.0k
           rest = val2 - cell0;
255
256
53.0k
           y0 = LutTable[cell0];
257
53.0k
           y1 = LutTable[cell1];
258
259
53.0k
           Output[0] = y0 + (y1 - y0) * rest;
260
53.0k
       }
261
115k
}
262
263
264
265
// Eval gray LUT having only one input channel
266
static CMS_NO_SANITIZE
267
void Eval1Input(CMSREGISTER const cmsUInt16Number Input[],
268
                CMSREGISTER cmsUInt16Number Output[],
269
                CMSREGISTER const cmsInterpParams* p16)
270
6.61k
{
271
6.61k
       cmsS15Fixed16Number fk;
272
6.61k
       cmsS15Fixed16Number k0, k1, rk, K0, K1;
273
6.61k
       int v;
274
6.61k
       cmsUInt32Number OutChan;
275
6.61k
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
276
277
278
       // if last value...
279
6.61k
       if (Input[0] == 0xffff || p16->Domain[0] == 0) {
280
281
1.46k
           cmsUInt32Number y0 = p16->Domain[0] * p16->opta[0];
282
           
283
5.84k
           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
284
4.38k
               Output[OutChan] = LutTable[y0 + OutChan];
285
4.38k
           }
286
1.46k
       }
287
5.15k
       else
288
5.15k
       {
289
290
5.15k
           v = Input[0] * p16->Domain[0];
291
5.15k
           fk = _cmsToFixedDomain(v);
292
293
5.15k
           k0 = FIXED_TO_INT(fk);
294
5.15k
           rk = (cmsUInt16Number)FIXED_REST_TO_INT(fk);
295
296
5.15k
           k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
297
298
5.15k
           K0 = p16->opta[0] * k0;
299
5.15k
           K1 = p16->opta[0] * k1;
300
301
20.6k
           for (OutChan = 0; OutChan < p16->nOutputs; OutChan++) {
302
303
15.4k
               Output[OutChan] = LinearInterp(rk, LutTable[K0 + OutChan], LutTable[K1 + OutChan]);
304
15.4k
           }
305
5.15k
       }
306
6.61k
}
307
308
309
310
// Eval gray LUT having only one input channel
311
static
312
void Eval1InputFloat(const cmsFloat32Number Value[],
313
                     cmsFloat32Number Output[],
314
                     const cmsInterpParams* p)
315
0
{
316
0
    cmsFloat32Number y1, y0;
317
0
    cmsFloat32Number val2, rest;
318
0
    int cell0, cell1;
319
0
    cmsUInt32Number OutChan;
320
0
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
321
322
0
    val2 = fclamp(Value[0]);
323
324
    // if last value...
325
0
    if (val2 == 1.0 || p->Domain[0] == 0) {
326
327
0
        cmsUInt32Number start = p->Domain[0] * p->opta[0];
328
329
0
        for (OutChan = 0; OutChan < p->nOutputs; OutChan++) {
330
0
            Output[OutChan] = LutTable[start + OutChan];
331
0
        }        
332
0
    }
333
0
    else
334
0
    {
335
0
        val2 *= p->Domain[0];
336
337
0
        cell0 = (int)floor(val2);
338
0
        cell1 = (int)ceil(val2);
339
340
        // Rest is 16 LSB bits
341
0
        rest = val2 - cell0;
342
343
0
        cell0 *= p->opta[0];
344
0
        cell1 *= p->opta[0];
345
346
0
        for (OutChan = 0; OutChan < p->nOutputs; OutChan++) {
347
348
0
            y0 = LutTable[cell0 + OutChan];
349
0
            y1 = LutTable[cell1 + OutChan];
350
351
0
            Output[OutChan] = y0 + (y1 - y0) * rest;
352
0
        }
353
0
    }
354
0
}
355
356
// Bilinear interpolation (16 bits) - cmsFloat32Number version
357
static
358
void BilinearInterpFloat(const cmsFloat32Number Input[],
359
                         cmsFloat32Number Output[],
360
                         const cmsInterpParams* p)
361
362
0
{
363
0
#   define LERP(a,l,h)    (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
364
0
#   define DENS(i,j)      (LutTable[(i)+(j)+OutChan])
365
366
0
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
367
0
    cmsFloat32Number      px, py;
368
0
    int        x0, y0,
369
0
               X0, Y0, X1, Y1;
370
0
    int        TotalOut, OutChan;
371
0
    cmsFloat32Number      fx, fy,
372
0
        d00, d01, d10, d11,
373
0
        dx0, dx1,
374
0
        dxy;
375
376
0
    TotalOut   = p -> nOutputs;
377
0
    px = fclamp(Input[0]) * p->Domain[0];
378
0
    py = fclamp(Input[1]) * p->Domain[1];
379
380
0
    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
381
0
    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
382
383
0
    X0 = p -> opta[1] * x0;
384
0
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[1]);
385
386
0
    Y0 = p -> opta[0] * y0;
387
0
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[0]);
388
389
0
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
390
391
0
        d00 = DENS(X0, Y0);
392
0
        d01 = DENS(X0, Y1);
393
0
        d10 = DENS(X1, Y0);
394
0
        d11 = DENS(X1, Y1);
395
396
0
        dx0 = LERP(fx, d00, d10);
397
0
        dx1 = LERP(fx, d01, d11);
398
399
0
        dxy = LERP(fy, dx0, dx1);
400
401
0
        Output[OutChan] = dxy;
402
0
    }
403
404
405
0
#   undef LERP
406
0
#   undef DENS
407
0
}
408
409
// Bilinear interpolation (16 bits) - optimized version
410
static CMS_NO_SANITIZE
411
void BilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
412
                      CMSREGISTER cmsUInt16Number Output[],
413
                      CMSREGISTER const cmsInterpParams* p)
414
415
624k
{
416
7.48M
#define DENS(i,j) (LutTable[(i)+(j)+OutChan])
417
5.61M
#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
418
419
624k
           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
420
624k
           int        OutChan, TotalOut;
421
624k
           cmsS15Fixed16Number    fx, fy;
422
624k
           CMSREGISTER int        rx, ry;
423
624k
           int                    x0, y0;
424
624k
           CMSREGISTER int        X0, X1, Y0, Y1;
425
426
624k
           int                    d00, d01, d10, d11,
427
624k
                                  dx0, dx1,
428
624k
                                  dxy;
429
430
624k
    TotalOut   = p -> nOutputs;
431
432
624k
    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
433
624k
    x0  = FIXED_TO_INT(fx);
434
624k
    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
435
436
437
624k
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
438
624k
    y0  = FIXED_TO_INT(fy);
439
624k
    ry  = FIXED_REST_TO_INT(fy);
440
441
442
624k
    X0 = p -> opta[1] * x0;
443
624k
    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
444
445
624k
    Y0 = p -> opta[0] * y0;
446
624k
    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
447
448
2.49M
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
449
450
1.87M
        d00 = DENS(X0, Y0);
451
1.87M
        d01 = DENS(X0, Y1);
452
1.87M
        d10 = DENS(X1, Y0);
453
1.87M
        d11 = DENS(X1, Y1);
454
455
1.87M
        dx0 = LERP(rx, d00, d10);
456
1.87M
        dx1 = LERP(rx, d01, d11);
457
458
1.87M
        dxy = LERP(ry, dx0, dx1);
459
460
1.87M
        Output[OutChan] = (cmsUInt16Number) dxy;
461
1.87M
    }
462
463
464
624k
#   undef LERP
465
624k
#   undef DENS
466
624k
}
467
468
469
// Trilinear interpolation (16 bits) - cmsFloat32Number version
470
static
471
void TrilinearInterpFloat(const cmsFloat32Number Input[],
472
                          cmsFloat32Number Output[],
473
                          const cmsInterpParams* p)
474
475
0
{
476
0
#   define LERP(a,l,h)      (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
477
0
#   define DENS(i,j,k)      (LutTable[(i)+(j)+(k)+OutChan])
478
479
0
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
480
0
    cmsFloat32Number      px, py, pz;
481
0
    int        x0, y0, z0,
482
0
               X0, Y0, Z0, X1, Y1, Z1;
483
0
    int        TotalOut, OutChan;
484
485
0
    cmsFloat32Number      fx, fy, fz,
486
0
                          d000, d001, d010, d011,
487
0
                          d100, d101, d110, d111,
488
0
                          dx00, dx01, dx10, dx11,
489
0
                          dxy0, dxy1, dxyz;
490
491
0
    TotalOut   = p -> nOutputs;
492
493
    // We need some clipping here
494
0
    px = fclamp(Input[0]) * p->Domain[0];
495
0
    py = fclamp(Input[1]) * p->Domain[1];
496
0
    pz = fclamp(Input[2]) * p->Domain[2];
497
498
0
    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor functionality here
499
0
    y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
500
0
    z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
501
502
0
    X0 = p -> opta[2] * x0;
503
0
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
504
505
0
    Y0 = p -> opta[1] * y0;
506
0
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
507
508
0
    Z0 = p -> opta[0] * z0;
509
0
    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
510
511
0
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
512
513
0
        d000 = DENS(X0, Y0, Z0);
514
0
        d001 = DENS(X0, Y0, Z1);
515
0
        d010 = DENS(X0, Y1, Z0);
516
0
        d011 = DENS(X0, Y1, Z1);
517
518
0
        d100 = DENS(X1, Y0, Z0);
519
0
        d101 = DENS(X1, Y0, Z1);
520
0
        d110 = DENS(X1, Y1, Z0);
521
0
        d111 = DENS(X1, Y1, Z1);
522
523
524
0
        dx00 = LERP(fx, d000, d100);
525
0
        dx01 = LERP(fx, d001, d101);
526
0
        dx10 = LERP(fx, d010, d110);
527
0
        dx11 = LERP(fx, d011, d111);
528
529
0
        dxy0 = LERP(fy, dx00, dx10);
530
0
        dxy1 = LERP(fy, dx01, dx11);
531
532
0
        dxyz = LERP(fz, dxy0, dxy1);
533
534
0
        Output[OutChan] = dxyz;
535
0
    }
536
537
538
0
#   undef LERP
539
0
#   undef DENS
540
0
}
541
542
// Trilinear interpolation (16 bits) - optimized version
543
static CMS_NO_SANITIZE
544
void TrilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
545
                       CMSREGISTER cmsUInt16Number Output[],
546
                       CMSREGISTER const cmsInterpParams* p)
547
548
13.8M
{
549
332M
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
550
291M
#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
551
552
13.8M
           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
553
13.8M
           int        OutChan, TotalOut;
554
13.8M
           cmsS15Fixed16Number    fx, fy, fz;
555
13.8M
           CMSREGISTER int        rx, ry, rz;
556
13.8M
           int                    x0, y0, z0;
557
13.8M
           CMSREGISTER int        X0, X1, Y0, Y1, Z0, Z1;
558
13.8M
           int                    d000, d001, d010, d011,
559
13.8M
                                  d100, d101, d110, d111,
560
13.8M
                                  dx00, dx01, dx10, dx11,
561
13.8M
                                  dxy0, dxy1, dxyz;
562
563
13.8M
    TotalOut   = p -> nOutputs;
564
565
13.8M
    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
566
13.8M
    x0  = FIXED_TO_INT(fx);
567
13.8M
    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
568
569
570
13.8M
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
571
13.8M
    y0  = FIXED_TO_INT(fy);
572
13.8M
    ry  = FIXED_REST_TO_INT(fy);
573
574
13.8M
    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
575
13.8M
    z0 = FIXED_TO_INT(fz);
576
13.8M
    rz = FIXED_REST_TO_INT(fz);
577
578
579
13.8M
    X0 = p -> opta[2] * x0;
580
13.8M
    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
581
582
13.8M
    Y0 = p -> opta[1] * y0;
583
13.8M
    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
584
585
13.8M
    Z0 = p -> opta[0] * z0;
586
13.8M
    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
587
588
55.4M
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
589
590
41.5M
        d000 = DENS(X0, Y0, Z0);
591
41.5M
        d001 = DENS(X0, Y0, Z1);
592
41.5M
        d010 = DENS(X0, Y1, Z0);
593
41.5M
        d011 = DENS(X0, Y1, Z1);
594
595
41.5M
        d100 = DENS(X1, Y0, Z0);
596
41.5M
        d101 = DENS(X1, Y0, Z1);
597
41.5M
        d110 = DENS(X1, Y1, Z0);
598
41.5M
        d111 = DENS(X1, Y1, Z1);
599
600
601
41.5M
        dx00 = LERP(rx, d000, d100);
602
41.5M
        dx01 = LERP(rx, d001, d101);
603
41.5M
        dx10 = LERP(rx, d010, d110);
604
41.5M
        dx11 = LERP(rx, d011, d111);
605
606
41.5M
        dxy0 = LERP(ry, dx00, dx10);
607
41.5M
        dxy1 = LERP(ry, dx01, dx11);
608
609
41.5M
        dxyz = LERP(rz, dxy0, dxy1);
610
611
41.5M
        Output[OutChan] = (cmsUInt16Number) dxyz;
612
41.5M
    }
613
614
615
13.8M
#   undef LERP
616
13.8M
#   undef DENS
617
13.8M
}
618
619
620
// Tetrahedral interpolation, using Sakamoto algorithm.
621
0
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
622
static
623
void TetrahedralInterpFloat(const cmsFloat32Number Input[],
624
                            cmsFloat32Number Output[],
625
                            const cmsInterpParams* p)
626
0
{
627
0
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
628
0
    cmsFloat32Number     px, py, pz;
629
0
    int                  x0, y0, z0,
630
0
                         X0, Y0, Z0, X1, Y1, Z1;
631
0
    cmsFloat32Number     rx, ry, rz;
632
0
    cmsFloat32Number     c0, c1=0, c2=0, c3=0;
633
0
    int                  OutChan, TotalOut;
634
635
0
    TotalOut   = p -> nOutputs;
636
637
    // We need some clipping here
638
0
    px = fclamp(Input[0]) * p->Domain[0];
639
0
    py = fclamp(Input[1]) * p->Domain[1];
640
0
    pz = fclamp(Input[2]) * p->Domain[2];
641
642
0
    x0 = (int) floor(px); rx = (px - (cmsFloat32Number) x0);  // We need full floor functionality here
643
0
    y0 = (int) floor(py); ry = (py - (cmsFloat32Number) y0);
644
0
    z0 = (int) floor(pz); rz = (pz - (cmsFloat32Number) z0);
645
646
647
0
    X0 = p -> opta[2] * x0;
648
0
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
649
650
0
    Y0 = p -> opta[1] * y0;
651
0
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
652
653
0
    Z0 = p -> opta[0] * z0;
654
0
    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
655
656
0
    for (OutChan=0; OutChan < TotalOut; OutChan++) {
657
658
       // These are the 6 Tetrahedral
659
660
0
        c0 = DENS(X0, Y0, Z0);
661
662
0
        if (rx >= ry && ry >= rz) {
663
664
0
            c1 = DENS(X1, Y0, Z0) - c0;
665
0
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
666
0
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
667
668
0
        }
669
0
        else
670
0
            if (rx >= rz && rz >= ry) {
671
672
0
                c1 = DENS(X1, Y0, Z0) - c0;
673
0
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
674
0
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
675
676
0
            }
677
0
            else
678
0
                if (rz >= rx && rx >= ry) {
679
680
0
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
681
0
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
682
0
                    c3 = DENS(X0, Y0, Z1) - c0;
683
684
0
                }
685
0
                else
686
0
                    if (ry >= rx && rx >= rz) {
687
688
0
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
689
0
                        c2 = DENS(X0, Y1, Z0) - c0;
690
0
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
691
692
0
                    }
693
0
                    else
694
0
                        if (ry >= rz && rz >= rx) {
695
696
0
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
697
0
                            c2 = DENS(X0, Y1, Z0) - c0;
698
0
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
699
700
0
                        }
701
0
                        else
702
0
                            if (rz >= ry && ry >= rx) {
703
704
0
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
705
0
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
706
0
                                c3 = DENS(X0, Y0, Z1) - c0;
707
708
0
                            }
709
0
                            else  {
710
0
                                c1 = c2 = c3 = 0;
711
0
                            }
712
713
0
       Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
714
0
       }
715
716
0
}
717
718
#undef DENS
719
720
static CMS_NO_SANITIZE
721
void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
722
                         CMSREGISTER cmsUInt16Number Output[],
723
                         CMSREGISTER const cmsInterpParams* p)
724
67.1M
{
725
67.1M
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
726
67.1M
    cmsS15Fixed16Number fx, fy, fz;
727
67.1M
    cmsS15Fixed16Number rx, ry, rz;
728
67.1M
    int x0, y0, z0;
729
67.1M
    cmsS15Fixed16Number c0, c1, c2, c3, Rest;
730
67.1M
    cmsUInt32Number X0, X1, Y0, Y1, Z0, Z1;
731
67.1M
    cmsUInt32Number TotalOut = p -> nOutputs;
732
733
67.1M
    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
734
67.1M
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
735
67.1M
    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
736
737
67.1M
    x0 = FIXED_TO_INT(fx);
738
67.1M
    y0 = FIXED_TO_INT(fy);
739
67.1M
    z0 = FIXED_TO_INT(fz);
740
741
67.1M
    rx = FIXED_REST_TO_INT(fx);
742
67.1M
    ry = FIXED_REST_TO_INT(fy);
743
67.1M
    rz = FIXED_REST_TO_INT(fz);
744
745
67.1M
    X0 = p -> opta[2] * x0;
746
67.1M
    X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
747
748
67.1M
    Y0 = p -> opta[1] * y0;
749
67.1M
    Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
750
751
67.1M
    Z0 = p -> opta[0] * z0;
752
67.1M
    Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
753
    
754
67.1M
    LutTable += X0+Y0+Z0;
755
756
    // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
757
    // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
758
    // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
759
    // at the cost of being off by one at 7fff and 17ffe.
760
761
67.1M
    if (rx >= ry) {
762
40.2M
        if (ry >= rz) {
763
20.4M
            Y1 += X1;
764
20.4M
            Z1 += Y1;
765
81.9M
            for (; TotalOut; TotalOut--) {
766
61.4M
                c1 = LutTable[X1];
767
61.4M
                c2 = LutTable[Y1];
768
61.4M
                c3 = LutTable[Z1];
769
61.4M
                c0 = *LutTable++;
770
61.4M
                c3 -= c2;
771
61.4M
                c2 -= c1;
772
61.4M
                c1 -= c0;
773
61.4M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
774
61.4M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
775
61.4M
            }
776
20.4M
        } else if (rz >= rx) {
777
10.2M
            X1 += Z1;
778
10.2M
            Y1 += X1;
779
40.9M
            for (; TotalOut; TotalOut--) {
780
30.7M
                c1 = LutTable[X1];
781
30.7M
                c2 = LutTable[Y1];
782
30.7M
                c3 = LutTable[Z1];
783
30.7M
                c0 = *LutTable++;
784
30.7M
                c2 -= c1;
785
30.7M
                c1 -= c3;
786
30.7M
                c3 -= c0;
787
30.7M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
788
30.7M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
789
30.7M
            }
790
10.2M
        } else {
791
9.51M
            Z1 += X1;
792
9.51M
            Y1 += Z1;
793
38.0M
            for (; TotalOut; TotalOut--) {
794
28.5M
                c1 = LutTable[X1];
795
28.5M
                c2 = LutTable[Y1];
796
28.5M
                c3 = LutTable[Z1];
797
28.5M
                c0 = *LutTable++;
798
28.5M
                c2 -= c3;
799
28.5M
                c3 -= c1;
800
28.5M
                c1 -= c0;
801
28.5M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
802
28.5M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
803
28.5M
            }
804
9.51M
        }
805
40.2M
    } else {
806
26.9M
        if (rx >= rz) {
807
11.0M
            X1 += Y1;
808
11.0M
            Z1 += X1;
809
44.0M
            for (; TotalOut; TotalOut--) {
810
33.0M
                c1 = LutTable[X1];
811
33.0M
                c2 = LutTable[Y1];
812
33.0M
                c3 = LutTable[Z1];
813
33.0M
                c0 = *LutTable++;
814
33.0M
                c3 -= c1;
815
33.0M
                c1 -= c2;
816
33.0M
                c2 -= c0;
817
33.0M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
818
33.0M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
819
33.0M
            }
820
15.9M
        } else if (ry >= rz) {
821
8.26M
            Z1 += Y1;
822
8.26M
            X1 += Z1;
823
33.0M
            for (; TotalOut; TotalOut--) {
824
24.8M
                c1 = LutTable[X1];
825
24.8M
                c2 = LutTable[Y1];
826
24.8M
                c3 = LutTable[Z1];
827
24.8M
                c0 = *LutTable++;
828
24.8M
                c1 -= c3;
829
24.8M
                c3 -= c2;
830
24.8M
                c2 -= c0;
831
24.8M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
832
24.8M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
833
24.8M
            }
834
8.26M
        } else {
835
7.65M
            Y1 += Z1;
836
7.65M
            X1 += Y1;
837
30.6M
            for (; TotalOut; TotalOut--) {
838
22.9M
                c1 = LutTable[X1];
839
22.9M
                c2 = LutTable[Y1];
840
22.9M
                c3 = LutTable[Z1];
841
22.9M
                c0 = *LutTable++;
842
22.9M
                c1 -= c2;
843
22.9M
                c2 -= c3;
844
22.9M
                c3 -= c0;
845
22.9M
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
846
22.9M
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
847
22.9M
            }
848
7.65M
        }
849
26.9M
    }
850
67.1M
}
851
852
853
3.30G
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
854
static CMS_NO_SANITIZE
855
void Eval4Inputs(CMSREGISTER const cmsUInt16Number Input[],
856
                     CMSREGISTER cmsUInt16Number Output[],
857
                     CMSREGISTER const cmsInterpParams* p16)
858
91.8M
{
859
91.8M
    const cmsUInt16Number* LutTable;
860
91.8M
    cmsS15Fixed16Number fk;
861
91.8M
    cmsS15Fixed16Number k0, rk;
862
91.8M
    int K0, K1;
863
91.8M
    cmsS15Fixed16Number    fx, fy, fz;
864
91.8M
    cmsS15Fixed16Number    rx, ry, rz;
865
91.8M
    int                    x0, y0, z0;
866
91.8M
    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
867
91.8M
    cmsUInt32Number i;
868
91.8M
    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
869
91.8M
    cmsUInt32Number        OutChan;
870
91.8M
    cmsUInt16Number        Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
871
872
873
91.8M
    fk  = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
874
91.8M
    fx  = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
875
91.8M
    fy  = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
876
91.8M
    fz  = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
877
878
91.8M
    k0  = FIXED_TO_INT(fk);
879
91.8M
    x0  = FIXED_TO_INT(fx);
880
91.8M
    y0  = FIXED_TO_INT(fy);
881
91.8M
    z0  = FIXED_TO_INT(fz);
882
883
91.8M
    rk  = FIXED_REST_TO_INT(fk);
884
91.8M
    rx  = FIXED_REST_TO_INT(fx);
885
91.8M
    ry  = FIXED_REST_TO_INT(fy);
886
91.8M
    rz  = FIXED_REST_TO_INT(fz);
887
888
91.8M
    K0 = p16 -> opta[3] * k0;
889
91.8M
    K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
890
891
91.8M
    X0 = p16 -> opta[2] * x0;
892
91.8M
    X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
893
894
91.8M
    Y0 = p16 -> opta[1] * y0;
895
91.8M
    Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
896
897
91.8M
    Z0 = p16 -> opta[0] * z0;
898
91.8M
    Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
899
900
91.8M
    LutTable = (cmsUInt16Number*) p16 -> Table;
901
91.8M
    LutTable += K0;
902
903
367M
    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
904
905
275M
        c0 = DENS(X0, Y0, Z0);
906
907
275M
        if (rx >= ry && ry >= rz) {
908
909
128M
            c1 = DENS(X1, Y0, Z0) - c0;
910
128M
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
911
128M
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
912
913
128M
        }
914
146M
        else
915
146M
            if (rx >= rz && rz >= ry) {
916
917
27.7M
                c1 = DENS(X1, Y0, Z0) - c0;
918
27.7M
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
919
27.7M
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
920
921
27.7M
            }
922
118M
            else
923
118M
                if (rz >= rx && rx >= ry) {
924
925
35.1M
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
926
35.1M
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
927
35.1M
                    c3 = DENS(X0, Y0, Z1) - c0;
928
929
35.1M
                }
930
83.7M
                else
931
83.7M
                    if (ry >= rx && rx >= rz) {
932
933
42.4M
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
934
42.4M
                        c2 = DENS(X0, Y1, Z0) - c0;
935
42.4M
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
936
937
42.4M
                    }
938
41.2M
                    else
939
41.2M
                        if (ry >= rz && rz >= rx) {
940
941
27.0M
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
942
27.0M
                            c2 = DENS(X0, Y1, Z0) - c0;
943
27.0M
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
944
945
27.0M
                        }
946
14.2M
                        else
947
14.2M
                            if (rz >= ry && ry >= rx) {
948
949
14.2M
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
950
14.2M
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
951
14.2M
                                c3 = DENS(X0, Y0, Z1) - c0;
952
953
14.2M
                            }
954
0
                            else {
955
0
                                c1 = c2 = c3 = 0;
956
0
                            }
957
958
275M
        Rest = c1 * rx + c2 * ry + c3 * rz;
959
960
275M
        Tmp1[OutChan] = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
961
275M
    }
962
963
964
91.8M
    LutTable = (cmsUInt16Number*) p16 -> Table;
965
91.8M
    LutTable += K1;
966
967
367M
    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
968
969
275M
        c0 = DENS(X0, Y0, Z0);
970
971
275M
        if (rx >= ry && ry >= rz) {
972
973
128M
            c1 = DENS(X1, Y0, Z0) - c0;
974
128M
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
975
128M
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
976
977
128M
        }
978
146M
        else
979
146M
            if (rx >= rz && rz >= ry) {
980
981
27.7M
                c1 = DENS(X1, Y0, Z0) - c0;
982
27.7M
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
983
27.7M
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
984
985
27.7M
            }
986
118M
            else
987
118M
                if (rz >= rx && rx >= ry) {
988
989
35.1M
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
990
35.1M
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
991
35.1M
                    c3 = DENS(X0, Y0, Z1) - c0;
992
993
35.1M
                }
994
83.7M
                else
995
83.7M
                    if (ry >= rx && rx >= rz) {
996
997
42.4M
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
998
42.4M
                        c2 = DENS(X0, Y1, Z0) - c0;
999
42.4M
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
1000
1001
42.4M
                    }
1002
41.2M
                    else
1003
41.2M
                        if (ry >= rz && rz >= rx) {
1004
1005
27.0M
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
1006
27.0M
                            c2 = DENS(X0, Y1, Z0) - c0;
1007
27.0M
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
1008
1009
27.0M
                        }
1010
14.2M
                        else
1011
14.2M
                            if (rz >= ry && ry >= rx) {
1012
1013
14.2M
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
1014
14.2M
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
1015
14.2M
                                c3 = DENS(X0, Y0, Z1) - c0;
1016
1017
14.2M
                            }
1018
0
                            else  {
1019
0
                                c1 = c2 = c3 = 0;
1020
0
                            }
1021
1022
275M
        Rest = c1 * rx + c2 * ry + c3 * rz;
1023
1024
275M
        Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
1025
275M
    }
1026
1027
1028
1029
367M
    for (i=0; i < p16 -> nOutputs; i++) {
1030
275M
        Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1031
275M
    }
1032
91.8M
}
1033
#undef DENS
1034
1035
1036
// For more that 3 inputs (i.e., CMYK)
1037
// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
1038
static
1039
void Eval4InputsFloat(const cmsFloat32Number Input[],
1040
                      cmsFloat32Number Output[],
1041
                      const cmsInterpParams* p)
1042
0
{
1043
0
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1044
0
       cmsFloat32Number rest;
1045
0
       cmsFloat32Number pk;
1046
0
       int k0, K0, K1;
1047
0
       const cmsFloat32Number* T;
1048
0
       cmsUInt32Number i;
1049
0
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1050
0
       cmsInterpParams p1;
1051
1052
0
       pk = fclamp(Input[0]) * p->Domain[0];
1053
0
       k0 = _cmsQuickFloor(pk);
1054
0
       rest = pk - (cmsFloat32Number) k0;
1055
1056
0
       K0 = p -> opta[3] * k0;
1057
0
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[3]);
1058
1059
0
       p1 = *p;
1060
0
       memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
1061
1062
0
       T = LutTable + K0;
1063
0
       p1.Table = T;
1064
1065
0
       TetrahedralInterpFloat(Input + 1,  Tmp1, &p1);
1066
1067
0
       T = LutTable + K1;
1068
0
       p1.Table = T;
1069
0
       TetrahedralInterpFloat(Input + 1,  Tmp2, &p1);
1070
1071
0
       for (i=0; i < p -> nOutputs; i++)
1072
0
       {
1073
0
              cmsFloat32Number y0 = Tmp1[i];
1074
0
              cmsFloat32Number y1 = Tmp2[i];
1075
1076
0
              Output[i] = y0 + (y1 - y0) * rest;
1077
0
       }
1078
0
}
1079
1080
#define EVAL_FNS(N,NM) static CMS_NO_SANITIZE \
1081
76.8M
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
76.8M
{\
1083
76.8M
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
76.8M
       cmsS15Fixed16Number fk;\
1085
76.8M
       cmsS15Fixed16Number k0, rk;\
1086
76.8M
       int K0, K1;\
1087
76.8M
       const cmsUInt16Number* T;\
1088
76.8M
       cmsUInt32Number i;\
1089
76.8M
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
76.8M
       cmsInterpParams p1;\
1091
76.8M
\
1092
76.8M
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
76.8M
       k0 = FIXED_TO_INT(fk);\
1094
76.8M
       rk = FIXED_REST_TO_INT(fk);\
1095
76.8M
\
1096
76.8M
       K0 = p16 -> opta[NM] * k0;\
1097
76.8M
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
76.8M
\
1099
76.8M
       p1 = *p16;\
1100
76.8M
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
76.8M
\
1102
76.8M
       T = LutTable + K0;\
1103
76.8M
       p1.Table = T;\
1104
76.8M
\
1105
76.8M
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
76.8M
\
1107
76.8M
       T = LutTable + K1;\
1108
76.8M
       p1.Table = T;\
1109
76.8M
\
1110
76.8M
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
76.8M
\
1112
307M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
230M
\
1114
230M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
230M
       }\
1116
76.8M
}\
cmsintrp.c:Eval5Inputs
Line
Count
Source
1081
43.2M
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
43.2M
{\
1083
43.2M
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
43.2M
       cmsS15Fixed16Number fk;\
1085
43.2M
       cmsS15Fixed16Number k0, rk;\
1086
43.2M
       int K0, K1;\
1087
43.2M
       const cmsUInt16Number* T;\
1088
43.2M
       cmsUInt32Number i;\
1089
43.2M
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
43.2M
       cmsInterpParams p1;\
1091
43.2M
\
1092
43.2M
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
43.2M
       k0 = FIXED_TO_INT(fk);\
1094
43.2M
       rk = FIXED_REST_TO_INT(fk);\
1095
43.2M
\
1096
43.2M
       K0 = p16 -> opta[NM] * k0;\
1097
43.2M
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
43.2M
\
1099
43.2M
       p1 = *p16;\
1100
43.2M
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
43.2M
\
1102
43.2M
       T = LutTable + K0;\
1103
43.2M
       p1.Table = T;\
1104
43.2M
\
1105
43.2M
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
43.2M
\
1107
43.2M
       T = LutTable + K1;\
1108
43.2M
       p1.Table = T;\
1109
43.2M
\
1110
43.2M
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
43.2M
\
1112
173M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
129M
\
1114
129M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
129M
       }\
1116
43.2M
}\
cmsintrp.c:Eval6Inputs
Line
Count
Source
1081
21.0M
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
21.0M
{\
1083
21.0M
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
21.0M
       cmsS15Fixed16Number fk;\
1085
21.0M
       cmsS15Fixed16Number k0, rk;\
1086
21.0M
       int K0, K1;\
1087
21.0M
       const cmsUInt16Number* T;\
1088
21.0M
       cmsUInt32Number i;\
1089
21.0M
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
21.0M
       cmsInterpParams p1;\
1091
21.0M
\
1092
21.0M
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
21.0M
       k0 = FIXED_TO_INT(fk);\
1094
21.0M
       rk = FIXED_REST_TO_INT(fk);\
1095
21.0M
\
1096
21.0M
       K0 = p16 -> opta[NM] * k0;\
1097
21.0M
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
21.0M
\
1099
21.0M
       p1 = *p16;\
1100
21.0M
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
21.0M
\
1102
21.0M
       T = LutTable + K0;\
1103
21.0M
       p1.Table = T;\
1104
21.0M
\
1105
21.0M
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
21.0M
\
1107
21.0M
       T = LutTable + K1;\
1108
21.0M
       p1.Table = T;\
1109
21.0M
\
1110
21.0M
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
21.0M
\
1112
84.1M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
63.0M
\
1114
63.0M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
63.0M
       }\
1116
21.0M
}\
cmsintrp.c:Eval7Inputs
Line
Count
Source
1081
8.78M
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
8.78M
{\
1083
8.78M
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
8.78M
       cmsS15Fixed16Number fk;\
1085
8.78M
       cmsS15Fixed16Number k0, rk;\
1086
8.78M
       int K0, K1;\
1087
8.78M
       const cmsUInt16Number* T;\
1088
8.78M
       cmsUInt32Number i;\
1089
8.78M
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
8.78M
       cmsInterpParams p1;\
1091
8.78M
\
1092
8.78M
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
8.78M
       k0 = FIXED_TO_INT(fk);\
1094
8.78M
       rk = FIXED_REST_TO_INT(fk);\
1095
8.78M
\
1096
8.78M
       K0 = p16 -> opta[NM] * k0;\
1097
8.78M
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
8.78M
\
1099
8.78M
       p1 = *p16;\
1100
8.78M
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
8.78M
\
1102
8.78M
       T = LutTable + K0;\
1103
8.78M
       p1.Table = T;\
1104
8.78M
\
1105
8.78M
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
8.78M
\
1107
8.78M
       T = LutTable + K1;\
1108
8.78M
       p1.Table = T;\
1109
8.78M
\
1110
8.78M
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
8.78M
\
1112
35.1M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
26.3M
\
1114
26.3M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
26.3M
       }\
1116
8.78M
}\
cmsintrp.c:Eval8Inputs
Line
Count
Source
1081
3.01M
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
3.01M
{\
1083
3.01M
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
3.01M
       cmsS15Fixed16Number fk;\
1085
3.01M
       cmsS15Fixed16Number k0, rk;\
1086
3.01M
       int K0, K1;\
1087
3.01M
       const cmsUInt16Number* T;\
1088
3.01M
       cmsUInt32Number i;\
1089
3.01M
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
3.01M
       cmsInterpParams p1;\
1091
3.01M
\
1092
3.01M
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
3.01M
       k0 = FIXED_TO_INT(fk);\
1094
3.01M
       rk = FIXED_REST_TO_INT(fk);\
1095
3.01M
\
1096
3.01M
       K0 = p16 -> opta[NM] * k0;\
1097
3.01M
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
3.01M
\
1099
3.01M
       p1 = *p16;\
1100
3.01M
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
3.01M
\
1102
3.01M
       T = LutTable + K0;\
1103
3.01M
       p1.Table = T;\
1104
3.01M
\
1105
3.01M
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
3.01M
\
1107
3.01M
       T = LutTable + K1;\
1108
3.01M
       p1.Table = T;\
1109
3.01M
\
1110
3.01M
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
3.01M
\
1112
12.0M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
9.04M
\
1114
9.04M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
9.04M
       }\
1116
3.01M
}\
cmsintrp.c:Eval9Inputs
Line
Count
Source
1081
540k
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
540k
{\
1083
540k
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
540k
       cmsS15Fixed16Number fk;\
1085
540k
       cmsS15Fixed16Number k0, rk;\
1086
540k
       int K0, K1;\
1087
540k
       const cmsUInt16Number* T;\
1088
540k
       cmsUInt32Number i;\
1089
540k
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
540k
       cmsInterpParams p1;\
1091
540k
\
1092
540k
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
540k
       k0 = FIXED_TO_INT(fk);\
1094
540k
       rk = FIXED_REST_TO_INT(fk);\
1095
540k
\
1096
540k
       K0 = p16 -> opta[NM] * k0;\
1097
540k
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
540k
\
1099
540k
       p1 = *p16;\
1100
540k
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
540k
\
1102
540k
       T = LutTable + K0;\
1103
540k
       p1.Table = T;\
1104
540k
\
1105
540k
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
540k
\
1107
540k
       T = LutTable + K1;\
1108
540k
       p1.Table = T;\
1109
540k
\
1110
540k
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
540k
\
1112
2.16M
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
1.62M
\
1114
1.62M
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
1.62M
       }\
1116
540k
}\
cmsintrp.c:Eval10Inputs
Line
Count
Source
1081
196k
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
196k
{\
1083
196k
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
196k
       cmsS15Fixed16Number fk;\
1085
196k
       cmsS15Fixed16Number k0, rk;\
1086
196k
       int K0, K1;\
1087
196k
       const cmsUInt16Number* T;\
1088
196k
       cmsUInt32Number i;\
1089
196k
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
196k
       cmsInterpParams p1;\
1091
196k
\
1092
196k
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
196k
       k0 = FIXED_TO_INT(fk);\
1094
196k
       rk = FIXED_REST_TO_INT(fk);\
1095
196k
\
1096
196k
       K0 = p16 -> opta[NM] * k0;\
1097
196k
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
196k
\
1099
196k
       p1 = *p16;\
1100
196k
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
196k
\
1102
196k
       T = LutTable + K0;\
1103
196k
       p1.Table = T;\
1104
196k
\
1105
196k
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
196k
\
1107
196k
       T = LutTable + K1;\
1108
196k
       p1.Table = T;\
1109
196k
\
1110
196k
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
196k
\
1112
784k
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
588k
\
1114
588k
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
588k
       }\
1116
196k
}\
cmsintrp.c:Eval11Inputs
Line
Count
Source
1081
288
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
288
{\
1083
288
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
288
       cmsS15Fixed16Number fk;\
1085
288
       cmsS15Fixed16Number k0, rk;\
1086
288
       int K0, K1;\
1087
288
       const cmsUInt16Number* T;\
1088
288
       cmsUInt32Number i;\
1089
288
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
288
       cmsInterpParams p1;\
1091
288
\
1092
288
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
288
       k0 = FIXED_TO_INT(fk);\
1094
288
       rk = FIXED_REST_TO_INT(fk);\
1095
288
\
1096
288
       K0 = p16 -> opta[NM] * k0;\
1097
288
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
288
\
1099
288
       p1 = *p16;\
1100
288
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
288
\
1102
288
       T = LutTable + K0;\
1103
288
       p1.Table = T;\
1104
288
\
1105
288
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
288
\
1107
288
       T = LutTable + K1;\
1108
288
       p1.Table = T;\
1109
288
\
1110
288
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
288
\
1112
1.15k
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
864
\
1114
864
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
864
       }\
1116
288
}\
cmsintrp.c:Eval12Inputs
Line
Count
Source
1081
144
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
144
{\
1083
144
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
144
       cmsS15Fixed16Number fk;\
1085
144
       cmsS15Fixed16Number k0, rk;\
1086
144
       int K0, K1;\
1087
144
       const cmsUInt16Number* T;\
1088
144
       cmsUInt32Number i;\
1089
144
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
144
       cmsInterpParams p1;\
1091
144
\
1092
144
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
144
       k0 = FIXED_TO_INT(fk);\
1094
144
       rk = FIXED_REST_TO_INT(fk);\
1095
144
\
1096
144
       K0 = p16 -> opta[NM] * k0;\
1097
144
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
144
\
1099
144
       p1 = *p16;\
1100
144
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
144
\
1102
144
       T = LutTable + K0;\
1103
144
       p1.Table = T;\
1104
144
\
1105
144
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
144
\
1107
144
       T = LutTable + K1;\
1108
144
       p1.Table = T;\
1109
144
\
1110
144
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
144
\
1112
576
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
432
\
1114
432
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
432
       }\
1116
144
}\
cmsintrp.c:Eval13Inputs
Line
Count
Source
1081
72
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
72
{\
1083
72
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
72
       cmsS15Fixed16Number fk;\
1085
72
       cmsS15Fixed16Number k0, rk;\
1086
72
       int K0, K1;\
1087
72
       const cmsUInt16Number* T;\
1088
72
       cmsUInt32Number i;\
1089
72
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
72
       cmsInterpParams p1;\
1091
72
\
1092
72
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
72
       k0 = FIXED_TO_INT(fk);\
1094
72
       rk = FIXED_REST_TO_INT(fk);\
1095
72
\
1096
72
       K0 = p16 -> opta[NM] * k0;\
1097
72
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
72
\
1099
72
       p1 = *p16;\
1100
72
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
72
\
1102
72
       T = LutTable + K0;\
1103
72
       p1.Table = T;\
1104
72
\
1105
72
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
72
\
1107
72
       T = LutTable + K1;\
1108
72
       p1.Table = T;\
1109
72
\
1110
72
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
72
\
1112
288
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
216
\
1114
216
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
216
       }\
1116
72
}\
cmsintrp.c:Eval14Inputs
Line
Count
Source
1081
36
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
36
{\
1083
36
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
36
       cmsS15Fixed16Number fk;\
1085
36
       cmsS15Fixed16Number k0, rk;\
1086
36
       int K0, K1;\
1087
36
       const cmsUInt16Number* T;\
1088
36
       cmsUInt32Number i;\
1089
36
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
36
       cmsInterpParams p1;\
1091
36
\
1092
36
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
36
       k0 = FIXED_TO_INT(fk);\
1094
36
       rk = FIXED_REST_TO_INT(fk);\
1095
36
\
1096
36
       K0 = p16 -> opta[NM] * k0;\
1097
36
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
36
\
1099
36
       p1 = *p16;\
1100
36
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
36
\
1102
36
       T = LutTable + K0;\
1103
36
       p1.Table = T;\
1104
36
\
1105
36
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
36
\
1107
36
       T = LutTable + K1;\
1108
36
       p1.Table = T;\
1109
36
\
1110
36
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
36
\
1112
144
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
108
\
1114
108
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
108
       }\
1116
36
}\
cmsintrp.c:Eval15Inputs
Line
Count
Source
1081
18
void Eval##N##Inputs(CMSREGISTER const cmsUInt16Number Input[], CMSREGISTER cmsUInt16Number Output[], CMSREGISTER const cmsInterpParams* p16)\
1082
18
{\
1083
18
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;\
1084
18
       cmsS15Fixed16Number fk;\
1085
18
       cmsS15Fixed16Number k0, rk;\
1086
18
       int K0, K1;\
1087
18
       const cmsUInt16Number* T;\
1088
18
       cmsUInt32Number i;\
1089
18
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1090
18
       cmsInterpParams p1;\
1091
18
\
1092
18
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);\
1093
18
       k0 = FIXED_TO_INT(fk);\
1094
18
       rk = FIXED_REST_TO_INT(fk);\
1095
18
\
1096
18
       K0 = p16 -> opta[NM] * k0;\
1097
18
       K1 = p16 -> opta[NM] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));\
1098
18
\
1099
18
       p1 = *p16;\
1100
18
       memmove(&p1.Domain[0], &p16 ->Domain[1], NM*sizeof(cmsUInt32Number));\
1101
18
\
1102
18
       T = LutTable + K0;\
1103
18
       p1.Table = T;\
1104
18
\
1105
18
       Eval##NM##Inputs(Input + 1, Tmp1, &p1);\
1106
18
\
1107
18
       T = LutTable + K1;\
1108
18
       p1.Table = T;\
1109
18
\
1110
18
       Eval##NM##Inputs(Input + 1, Tmp2, &p1);\
1111
18
\
1112
72
       for (i=0; i < p16 -> nOutputs; i++) {\
1113
54
\
1114
54
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);\
1115
54
       }\
1116
18
}\
1117
\
1118
static void Eval##N##InputsFloat(const cmsFloat32Number Input[], \
1119
                                 cmsFloat32Number Output[],\
1120
0
                                 const cmsInterpParams * p)\
1121
0
{\
1122
0
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;\
1123
0
       cmsFloat32Number rest;\
1124
0
       cmsFloat32Number pk;\
1125
0
       int k0, K0, K1;\
1126
0
       const cmsFloat32Number* T;\
1127
0
       cmsUInt32Number i;\
1128
0
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];\
1129
0
       cmsInterpParams p1;\
1130
0
\
1131
0
       pk = fclamp(Input[0]) * p->Domain[0];\
1132
0
       k0 = _cmsQuickFloor(pk);\
1133
0
       rest = pk - (cmsFloat32Number) k0;\
1134
0
\
1135
0
       K0 = p -> opta[NM] * k0;\
1136
0
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[NM]);\
1137
0
\
1138
0
       p1 = *p;\
1139
0
       memmove(&p1.Domain[0], &p ->Domain[1], NM*sizeof(cmsUInt32Number));\
1140
0
\
1141
0
       T = LutTable + K0;\
1142
0
       p1.Table = T;\
1143
0
\
1144
0
       Eval##NM##InputsFloat(Input + 1, Tmp1, &p1);\
1145
0
\
1146
0
       T = LutTable + K1;\
1147
0
       p1.Table = T;\
1148
0
\
1149
0
       Eval##NM##InputsFloat(Input + 1, Tmp2, &p1);\
1150
0
\
1151
0
       for (i=0; i < p -> nOutputs; i++) {\
1152
0
\
1153
0
              cmsFloat32Number y0 = Tmp1[i];\
1154
0
              cmsFloat32Number y1 = Tmp2[i];\
1155
0
\
1156
0
              Output[i] = y0 + (y1 - y0) * rest;\
1157
0
       }\
1158
0
}
Unexecuted instantiation: cmsintrp.c:Eval5InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval6InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval7InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval8InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval9InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval10InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval11InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval12InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval13InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval14InputsFloat
Unexecuted instantiation: cmsintrp.c:Eval15InputsFloat
1159
1160
1161
/**
1162
* Thanks to Carles Llopis for the templating idea
1163
*/
1164
EVAL_FNS(5, 4)
1165
EVAL_FNS(6, 5)
1166
EVAL_FNS(7, 6)
1167
EVAL_FNS(8, 7)
1168
EVAL_FNS(9, 8)
1169
EVAL_FNS(10, 9)
1170
EVAL_FNS(11, 10)
1171
EVAL_FNS(12, 11)
1172
EVAL_FNS(13, 12)
1173
EVAL_FNS(14, 13)
1174
EVAL_FNS(15, 14)
1175
1176
1177
// The default factory
1178
static
1179
cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
1180
70.1k
{
1181
1182
70.1k
    cmsInterpFunction Interpolation;
1183
70.1k
    cmsBool  IsFloat     = (dwFlags & CMS_LERP_FLAGS_FLOAT);
1184
70.1k
    cmsBool  IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
1185
1186
70.1k
    memset(&Interpolation, 0, sizeof(Interpolation));
1187
1188
    // Safety check
1189
70.1k
    if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
1190
0
        return Interpolation;
1191
1192
70.1k
    switch (nInputChannels) {
1193
1194
60.8k
           case 1: // Gray LUT / linear
1195
1196
60.8k
               if (nOutputChannels == 1) {
1197
1198
59.9k
                   if (IsFloat)
1199
580
                       Interpolation.LerpFloat = LinLerp1Dfloat;
1200
59.3k
                   else
1201
59.3k
                       Interpolation.Lerp16 = LinLerp1D;
1202
1203
59.9k
               }
1204
886
               else {
1205
1206
886
                   if (IsFloat)
1207
7
                       Interpolation.LerpFloat = Eval1InputFloat;
1208
879
                   else
1209
879
                       Interpolation.Lerp16 = Eval1Input;
1210
886
               }
1211
60.8k
               break;
1212
1213
364
           case 2: // Duotone
1214
364
               if (IsFloat)
1215
3
                      Interpolation.LerpFloat =  BilinearInterpFloat;
1216
361
               else
1217
361
                      Interpolation.Lerp16    =  BilinearInterp16;
1218
364
               break;
1219
1220
7.32k
           case 3:  // RGB et al
1221
1222
7.32k
               if (IsTrilinear) {
1223
1224
2.44k
                   if (IsFloat)
1225
0
                       Interpolation.LerpFloat = TrilinearInterpFloat;
1226
2.44k
                   else
1227
2.44k
                       Interpolation.Lerp16 = TrilinearInterp16;
1228
2.44k
               }
1229
4.87k
               else {
1230
1231
4.87k
                   if (IsFloat)
1232
17
                       Interpolation.LerpFloat = TetrahedralInterpFloat;
1233
4.85k
                   else {
1234
1235
4.85k
                       Interpolation.Lerp16 = TetrahedralInterp16;
1236
4.85k
                   }
1237
4.87k
               }
1238
7.32k
               break;
1239
1240
697
           case 4:  // CMYK lut
1241
1242
697
               if (IsFloat)
1243
23
                   Interpolation.LerpFloat =  Eval4InputsFloat;
1244
674
               else
1245
674
                   Interpolation.Lerp16    =  Eval4Inputs;
1246
697
               break;
1247
1248
131
           case 5: // 5 Inks
1249
131
               if (IsFloat)
1250
5
                   Interpolation.LerpFloat =  Eval5InputsFloat;
1251
126
               else
1252
126
                   Interpolation.Lerp16    =  Eval5Inputs;
1253
131
               break;
1254
1255
108
           case 6: // 6 Inks
1256
108
               if (IsFloat)
1257
6
                   Interpolation.LerpFloat =  Eval6InputsFloat;
1258
102
               else
1259
102
                   Interpolation.Lerp16    =  Eval6Inputs;
1260
108
               break;
1261
1262
120
           case 7: // 7 inks
1263
120
               if (IsFloat)
1264
3
                   Interpolation.LerpFloat =  Eval7InputsFloat;
1265
117
               else
1266
117
                   Interpolation.Lerp16    =  Eval7Inputs;
1267
120
               break;
1268
1269
194
           case 8: // 8 inks
1270
194
               if (IsFloat)
1271
5
                   Interpolation.LerpFloat =  Eval8InputsFloat;
1272
189
               else
1273
189
                   Interpolation.Lerp16    =  Eval8Inputs;
1274
194
               break;
1275
1276
159
           case 9: 
1277
159
               if (IsFloat)
1278
1
                   Interpolation.LerpFloat = Eval9InputsFloat;
1279
158
               else
1280
158
                   Interpolation.Lerp16 = Eval9Inputs;
1281
159
               break;
1282
1283
148
           case 10: 
1284
148
               if (IsFloat)
1285
1
                   Interpolation.LerpFloat = Eval10InputsFloat;
1286
147
               else
1287
147
                   Interpolation.Lerp16 = Eval10Inputs;
1288
148
               break;
1289
1290
11
           case 11:
1291
11
               if (IsFloat)
1292
1
                   Interpolation.LerpFloat = Eval11InputsFloat;
1293
10
               else
1294
10
                   Interpolation.Lerp16 = Eval11Inputs;
1295
11
               break;
1296
1297
11
           case 12: 
1298
11
               if (IsFloat)
1299
1
                   Interpolation.LerpFloat = Eval12InputsFloat;
1300
10
               else
1301
10
                   Interpolation.Lerp16 = Eval12Inputs;
1302
11
               break;
1303
1304
13
           case 13: 
1305
13
               if (IsFloat)
1306
1
                   Interpolation.LerpFloat = Eval13InputsFloat;
1307
12
               else
1308
12
                   Interpolation.Lerp16 = Eval13Inputs;
1309
13
               break;
1310
1311
12
           case 14: 
1312
12
               if (IsFloat)
1313
1
                   Interpolation.LerpFloat = Eval14InputsFloat;
1314
11
               else
1315
11
                   Interpolation.Lerp16 = Eval14Inputs;
1316
12
               break;
1317
1318
77
           case 15: 
1319
77
               if (IsFloat)
1320
1
                   Interpolation.LerpFloat = Eval15InputsFloat;
1321
76
               else
1322
76
                   Interpolation.Lerp16 = Eval15Inputs;
1323
77
               break;
1324
1325
0
           default:
1326
0
               Interpolation.Lerp16 = NULL;
1327
70.1k
    }
1328
1329
70.1k
    return Interpolation;
1330
70.1k
}