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