Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/java2d/cmm/lcms/cmsintrp.c
38918 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
int d00, d01, d10, d11,
441
dx0, dx1,
442
dxy;
443
444
TotalOut = p -> nOutputs;
445
446
fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
447
x0 = FIXED_TO_INT(fx);
448
rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
449
450
451
fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
452
y0 = FIXED_TO_INT(fy);
453
ry = FIXED_REST_TO_INT(fy);
454
455
456
X0 = p -> opta[1] * x0;
457
X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
458
459
Y0 = p -> opta[0] * y0;
460
Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
461
462
for (OutChan = 0; OutChan < TotalOut; OutChan++) {
463
464
d00 = DENS(X0, Y0);
465
d01 = DENS(X0, Y1);
466
d10 = DENS(X1, Y0);
467
d11 = DENS(X1, Y1);
468
469
dx0 = LERP(rx, d00, d10);
470
dx1 = LERP(rx, d01, d11);
471
472
dxy = LERP(ry, dx0, dx1);
473
474
Output[OutChan] = (cmsUInt16Number) dxy;
475
}
476
477
478
# undef LERP
479
# undef DENS
480
}
481
482
483
// Trilinear interpolation (16 bits) - cmsFloat32Number version
484
static
485
void TrilinearInterpFloat(const cmsFloat32Number Input[],
486
cmsFloat32Number Output[],
487
const cmsInterpParams* p)
488
489
{
490
# define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
491
# define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
492
493
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
494
cmsFloat32Number px, py, pz;
495
int x0, y0, z0,
496
X0, Y0, Z0, X1, Y1, Z1;
497
int TotalOut, OutChan;
498
cmsFloat32Number fx, fy, fz,
499
d000, d001, d010, d011,
500
d100, d101, d110, d111,
501
dx00, dx01, dx10, dx11,
502
dxy0, dxy1, dxyz;
503
504
TotalOut = p -> nOutputs;
505
506
// We need some clipping here
507
px = fclamp(Input[0]) * p->Domain[0];
508
py = fclamp(Input[1]) * p->Domain[1];
509
pz = fclamp(Input[2]) * p->Domain[2];
510
511
x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0; // We need full floor funcionality here
512
y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
513
z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
514
515
X0 = p -> opta[2] * x0;
516
X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
517
518
Y0 = p -> opta[1] * y0;
519
Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
520
521
Z0 = p -> opta[0] * z0;
522
Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
523
524
for (OutChan = 0; OutChan < TotalOut; OutChan++) {
525
526
d000 = DENS(X0, Y0, Z0);
527
d001 = DENS(X0, Y0, Z1);
528
d010 = DENS(X0, Y1, Z0);
529
d011 = DENS(X0, Y1, Z1);
530
531
d100 = DENS(X1, Y0, Z0);
532
d101 = DENS(X1, Y0, Z1);
533
d110 = DENS(X1, Y1, Z0);
534
d111 = DENS(X1, Y1, Z1);
535
536
537
dx00 = LERP(fx, d000, d100);
538
dx01 = LERP(fx, d001, d101);
539
dx10 = LERP(fx, d010, d110);
540
dx11 = LERP(fx, d011, d111);
541
542
dxy0 = LERP(fy, dx00, dx10);
543
dxy1 = LERP(fy, dx01, dx11);
544
545
dxyz = LERP(fz, dxy0, dxy1);
546
547
Output[OutChan] = dxyz;
548
}
549
550
551
# undef LERP
552
# undef DENS
553
}
554
555
// Trilinear interpolation (16 bits) - optimized version
556
static CMS_NO_SANITIZE
557
void TrilinearInterp16(CMSREGISTER const cmsUInt16Number Input[],
558
CMSREGISTER cmsUInt16Number Output[],
559
CMSREGISTER const cmsInterpParams* p)
560
561
{
562
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
563
#define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
564
565
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
566
int OutChan, TotalOut;
567
cmsS15Fixed16Number fx, fy, fz;
568
CMSREGISTER int rx, ry, rz;
569
int x0, y0, z0;
570
CMSREGISTER int X0, X1, Y0, Y1, Z0, Z1;
571
int d000, d001, d010, d011,
572
d100, d101, d110, d111,
573
dx00, dx01, dx10, dx11,
574
dxy0, dxy1, dxyz;
575
576
TotalOut = p -> nOutputs;
577
578
fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
579
x0 = FIXED_TO_INT(fx);
580
rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
581
582
583
fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
584
y0 = FIXED_TO_INT(fy);
585
ry = FIXED_REST_TO_INT(fy);
586
587
fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
588
z0 = FIXED_TO_INT(fz);
589
rz = FIXED_REST_TO_INT(fz);
590
591
592
X0 = p -> opta[2] * x0;
593
X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
594
595
Y0 = p -> opta[1] * y0;
596
Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
597
598
Z0 = p -> opta[0] * z0;
599
Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
600
601
for (OutChan = 0; OutChan < TotalOut; OutChan++) {
602
603
d000 = DENS(X0, Y0, Z0);
604
d001 = DENS(X0, Y0, Z1);
605
d010 = DENS(X0, Y1, Z0);
606
d011 = DENS(X0, Y1, Z1);
607
608
d100 = DENS(X1, Y0, Z0);
609
d101 = DENS(X1, Y0, Z1);
610
d110 = DENS(X1, Y1, Z0);
611
d111 = DENS(X1, Y1, Z1);
612
613
614
dx00 = LERP(rx, d000, d100);
615
dx01 = LERP(rx, d001, d101);
616
dx10 = LERP(rx, d010, d110);
617
dx11 = LERP(rx, d011, d111);
618
619
dxy0 = LERP(ry, dx00, dx10);
620
dxy1 = LERP(ry, dx01, dx11);
621
622
dxyz = LERP(rz, dxy0, dxy1);
623
624
Output[OutChan] = (cmsUInt16Number) dxyz;
625
}
626
627
628
# undef LERP
629
# undef DENS
630
}
631
632
633
// Tetrahedral interpolation, using Sakamoto algorithm.
634
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
635
static
636
void TetrahedralInterpFloat(const cmsFloat32Number Input[],
637
cmsFloat32Number Output[],
638
const cmsInterpParams* p)
639
{
640
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
641
cmsFloat32Number px, py, pz;
642
int x0, y0, z0,
643
X0, Y0, Z0, X1, Y1, Z1;
644
cmsFloat32Number rx, ry, rz;
645
cmsFloat32Number c0, c1=0, c2=0, c3=0;
646
int OutChan, TotalOut;
647
648
TotalOut = p -> nOutputs;
649
650
// We need some clipping here
651
px = fclamp(Input[0]) * p->Domain[0];
652
py = fclamp(Input[1]) * p->Domain[1];
653
pz = fclamp(Input[2]) * p->Domain[2];
654
655
x0 = (int) floor(px); rx = (px - (cmsFloat32Number) x0); // We need full floor functionality here
656
y0 = (int) floor(py); ry = (py - (cmsFloat32Number) y0);
657
z0 = (int) floor(pz); rz = (pz - (cmsFloat32Number) z0);
658
659
660
X0 = p -> opta[2] * x0;
661
X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
662
663
Y0 = p -> opta[1] * y0;
664
Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
665
666
Z0 = p -> opta[0] * z0;
667
Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
668
669
for (OutChan=0; OutChan < TotalOut; OutChan++) {
670
671
// These are the 6 Tetrahedral
672
673
c0 = DENS(X0, Y0, Z0);
674
675
if (rx >= ry && ry >= rz) {
676
677
c1 = DENS(X1, Y0, Z0) - c0;
678
c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
679
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
680
681
}
682
else
683
if (rx >= rz && rz >= ry) {
684
685
c1 = DENS(X1, Y0, Z0) - c0;
686
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
687
c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
688
689
}
690
else
691
if (rz >= rx && rx >= ry) {
692
693
c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
694
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
695
c3 = DENS(X0, Y0, Z1) - c0;
696
697
}
698
else
699
if (ry >= rx && rx >= rz) {
700
701
c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
702
c2 = DENS(X0, Y1, Z0) - c0;
703
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
704
705
}
706
else
707
if (ry >= rz && rz >= rx) {
708
709
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
710
c2 = DENS(X0, Y1, Z0) - c0;
711
c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
712
713
}
714
else
715
if (rz >= ry && ry >= rx) {
716
717
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
718
c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
719
c3 = DENS(X0, Y0, Z1) - c0;
720
721
}
722
else {
723
c1 = c2 = c3 = 0;
724
}
725
726
Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
727
}
728
729
}
730
731
#undef DENS
732
733
734
735
736
static CMS_NO_SANITIZE
737
void TetrahedralInterp16(CMSREGISTER const cmsUInt16Number Input[],
738
CMSREGISTER cmsUInt16Number Output[],
739
CMSREGISTER const cmsInterpParams* p)
740
{
741
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
742
cmsS15Fixed16Number fx, fy, fz;
743
cmsS15Fixed16Number rx, ry, rz;
744
int x0, y0, z0;
745
cmsS15Fixed16Number c0, c1, c2, c3, Rest;
746
cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
747
cmsUInt32Number TotalOut = p -> nOutputs;
748
749
fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
750
fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
751
fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
752
753
x0 = FIXED_TO_INT(fx);
754
y0 = FIXED_TO_INT(fy);
755
z0 = FIXED_TO_INT(fz);
756
757
rx = FIXED_REST_TO_INT(fx);
758
ry = FIXED_REST_TO_INT(fy);
759
rz = FIXED_REST_TO_INT(fz);
760
761
X0 = p -> opta[2] * x0;
762
X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
763
764
Y0 = p -> opta[1] * y0;
765
Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
766
767
Z0 = p -> opta[0] * z0;
768
Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
769
770
LutTable = &LutTable[X0+Y0+Z0];
771
772
// Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
773
// which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
774
// This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
775
// at the cost of being off by one at 7fff and 17ffe.
776
777
if (rx >= ry) {
778
if (ry >= rz) {
779
Y1 += X1;
780
Z1 += Y1;
781
for (; TotalOut; TotalOut--) {
782
c1 = LutTable[X1];
783
c2 = LutTable[Y1];
784
c3 = LutTable[Z1];
785
c0 = *LutTable++;
786
c3 -= c2;
787
c2 -= c1;
788
c1 -= c0;
789
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
790
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
791
}
792
} else if (rz >= rx) {
793
X1 += Z1;
794
Y1 += X1;
795
for (; TotalOut; TotalOut--) {
796
c1 = LutTable[X1];
797
c2 = LutTable[Y1];
798
c3 = LutTable[Z1];
799
c0 = *LutTable++;
800
c2 -= c1;
801
c1 -= c3;
802
c3 -= c0;
803
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
804
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
805
}
806
} else {
807
Z1 += X1;
808
Y1 += Z1;
809
for (; TotalOut; TotalOut--) {
810
c1 = LutTable[X1];
811
c2 = LutTable[Y1];
812
c3 = LutTable[Z1];
813
c0 = *LutTable++;
814
c2 -= c3;
815
c3 -= c1;
816
c1 -= c0;
817
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
818
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
819
}
820
}
821
} else {
822
if (rx >= rz) {
823
X1 += Y1;
824
Z1 += X1;
825
for (; TotalOut; TotalOut--) {
826
c1 = LutTable[X1];
827
c2 = LutTable[Y1];
828
c3 = LutTable[Z1];
829
c0 = *LutTable++;
830
c3 -= c1;
831
c1 -= c2;
832
c2 -= c0;
833
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
834
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
835
}
836
} else if (ry >= rz) {
837
Z1 += Y1;
838
X1 += Z1;
839
for (; TotalOut; TotalOut--) {
840
c1 = LutTable[X1];
841
c2 = LutTable[Y1];
842
c3 = LutTable[Z1];
843
c0 = *LutTable++;
844
c1 -= c3;
845
c3 -= c2;
846
c2 -= c0;
847
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
848
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
849
}
850
} else {
851
Y1 += Z1;
852
X1 += Y1;
853
for (; TotalOut; TotalOut--) {
854
c1 = LutTable[X1];
855
c2 = LutTable[Y1];
856
c3 = LutTable[Z1];
857
c0 = *LutTable++;
858
c1 -= c2;
859
c2 -= c3;
860
c3 -= c0;
861
Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
862
*Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
863
}
864
}
865
}
866
}
867
868
869
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
870
static CMS_NO_SANITIZE
871
void Eval4Inputs(CMSREGISTER const cmsUInt16Number Input[],
872
CMSREGISTER cmsUInt16Number Output[],
873
CMSREGISTER const cmsInterpParams* p16)
874
{
875
const cmsUInt16Number* LutTable;
876
cmsS15Fixed16Number fk;
877
cmsS15Fixed16Number k0, rk;
878
int K0, K1;
879
cmsS15Fixed16Number fx, fy, fz;
880
cmsS15Fixed16Number rx, ry, rz;
881
int x0, y0, z0;
882
cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
883
cmsUInt32Number i;
884
cmsS15Fixed16Number c0, c1, c2, c3, Rest;
885
cmsUInt32Number OutChan;
886
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
887
888
889
fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
890
fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
891
fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
892
fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
893
894
k0 = FIXED_TO_INT(fk);
895
x0 = FIXED_TO_INT(fx);
896
y0 = FIXED_TO_INT(fy);
897
z0 = FIXED_TO_INT(fz);
898
899
rk = FIXED_REST_TO_INT(fk);
900
rx = FIXED_REST_TO_INT(fx);
901
ry = FIXED_REST_TO_INT(fy);
902
rz = FIXED_REST_TO_INT(fz);
903
904
K0 = p16 -> opta[3] * k0;
905
K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
906
907
X0 = p16 -> opta[2] * x0;
908
X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
909
910
Y0 = p16 -> opta[1] * y0;
911
Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
912
913
Z0 = p16 -> opta[0] * z0;
914
Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
915
916
LutTable = (cmsUInt16Number*) p16 -> Table;
917
LutTable += K0;
918
919
for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
920
921
c0 = DENS(X0, Y0, Z0);
922
923
if (rx >= ry && ry >= rz) {
924
925
c1 = DENS(X1, Y0, Z0) - c0;
926
c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
927
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
928
929
}
930
else
931
if (rx >= rz && rz >= ry) {
932
933
c1 = DENS(X1, Y0, Z0) - c0;
934
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
935
c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
936
937
}
938
else
939
if (rz >= rx && rx >= ry) {
940
941
c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
942
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
943
c3 = DENS(X0, Y0, Z1) - c0;
944
945
}
946
else
947
if (ry >= rx && rx >= rz) {
948
949
c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
950
c2 = DENS(X0, Y1, Z0) - c0;
951
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
952
953
}
954
else
955
if (ry >= rz && rz >= rx) {
956
957
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
958
c2 = DENS(X0, Y1, Z0) - c0;
959
c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
960
961
}
962
else
963
if (rz >= ry && ry >= rx) {
964
965
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
966
c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
967
c3 = DENS(X0, Y0, Z1) - c0;
968
969
}
970
else {
971
c1 = c2 = c3 = 0;
972
}
973
974
Rest = c1 * rx + c2 * ry + c3 * rz;
975
976
Tmp1[OutChan] = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
977
}
978
979
980
LutTable = (cmsUInt16Number*) p16 -> Table;
981
LutTable += K1;
982
983
for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
984
985
c0 = DENS(X0, Y0, Z0);
986
987
if (rx >= ry && ry >= rz) {
988
989
c1 = DENS(X1, Y0, Z0) - c0;
990
c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
991
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
992
993
}
994
else
995
if (rx >= rz && rz >= ry) {
996
997
c1 = DENS(X1, Y0, Z0) - c0;
998
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
999
c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
1000
1001
}
1002
else
1003
if (rz >= rx && rx >= ry) {
1004
1005
c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
1006
c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
1007
c3 = DENS(X0, Y0, Z1) - c0;
1008
1009
}
1010
else
1011
if (ry >= rx && rx >= rz) {
1012
1013
c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
1014
c2 = DENS(X0, Y1, Z0) - c0;
1015
c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
1016
1017
}
1018
else
1019
if (ry >= rz && rz >= rx) {
1020
1021
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
1022
c2 = DENS(X0, Y1, Z0) - c0;
1023
c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
1024
1025
}
1026
else
1027
if (rz >= ry && ry >= rx) {
1028
1029
c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
1030
c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
1031
c3 = DENS(X0, Y0, Z1) - c0;
1032
1033
}
1034
else {
1035
c1 = c2 = c3 = 0;
1036
}
1037
1038
Rest = c1 * rx + c2 * ry + c3 * rz;
1039
1040
Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
1041
}
1042
1043
1044
1045
for (i=0; i < p16 -> nOutputs; i++) {
1046
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1047
}
1048
}
1049
#undef DENS
1050
1051
1052
// For more that 3 inputs (i.e., CMYK)
1053
// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
1054
1055
1056
static
1057
void Eval4InputsFloat(const cmsFloat32Number Input[],
1058
cmsFloat32Number Output[],
1059
const cmsInterpParams* p)
1060
{
1061
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1062
cmsFloat32Number rest;
1063
cmsFloat32Number pk;
1064
int k0, K0, K1;
1065
const cmsFloat32Number* T;
1066
cmsUInt32Number i;
1067
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1068
cmsInterpParams p1;
1069
1070
pk = fclamp(Input[0]) * p->Domain[0];
1071
k0 = _cmsQuickFloor(pk);
1072
rest = pk - (cmsFloat32Number) k0;
1073
1074
K0 = p -> opta[3] * k0;
1075
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[3]);
1076
1077
p1 = *p;
1078
memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
1079
1080
T = LutTable + K0;
1081
p1.Table = T;
1082
1083
TetrahedralInterpFloat(Input + 1, Tmp1, &p1);
1084
1085
T = LutTable + K1;
1086
p1.Table = T;
1087
TetrahedralInterpFloat(Input + 1, Tmp2, &p1);
1088
1089
for (i=0; i < p -> nOutputs; i++)
1090
{
1091
cmsFloat32Number y0 = Tmp1[i];
1092
cmsFloat32Number y1 = Tmp2[i];
1093
1094
Output[i] = y0 + (y1 - y0) * rest;
1095
}
1096
}
1097
1098
1099
static CMS_NO_SANITIZE
1100
void Eval5Inputs(CMSREGISTER const cmsUInt16Number Input[],
1101
CMSREGISTER cmsUInt16Number Output[],
1102
1103
CMSREGISTER const cmsInterpParams* p16)
1104
{
1105
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1106
cmsS15Fixed16Number fk;
1107
cmsS15Fixed16Number k0, rk;
1108
int K0, K1;
1109
const cmsUInt16Number* T;
1110
cmsUInt32Number i;
1111
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1112
cmsInterpParams p1;
1113
1114
1115
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1116
k0 = FIXED_TO_INT(fk);
1117
rk = FIXED_REST_TO_INT(fk);
1118
1119
K0 = p16 -> opta[4] * k0;
1120
K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1121
1122
p1 = *p16;
1123
memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
1124
1125
T = LutTable + K0;
1126
p1.Table = T;
1127
1128
Eval4Inputs(Input + 1, Tmp1, &p1);
1129
1130
T = LutTable + K1;
1131
p1.Table = T;
1132
1133
Eval4Inputs(Input + 1, Tmp2, &p1);
1134
1135
for (i=0; i < p16 -> nOutputs; i++) {
1136
1137
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1138
}
1139
1140
}
1141
1142
1143
static
1144
void Eval5InputsFloat(const cmsFloat32Number Input[],
1145
cmsFloat32Number Output[],
1146
const cmsInterpParams* p)
1147
{
1148
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1149
cmsFloat32Number rest;
1150
cmsFloat32Number pk;
1151
int k0, K0, K1;
1152
const cmsFloat32Number* T;
1153
cmsUInt32Number i;
1154
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1155
cmsInterpParams p1;
1156
1157
pk = fclamp(Input[0]) * p->Domain[0];
1158
k0 = _cmsQuickFloor(pk);
1159
rest = pk - (cmsFloat32Number) k0;
1160
1161
K0 = p -> opta[4] * k0;
1162
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
1163
1164
p1 = *p;
1165
memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
1166
1167
T = LutTable + K0;
1168
p1.Table = T;
1169
1170
Eval4InputsFloat(Input + 1, Tmp1, &p1);
1171
1172
T = LutTable + K1;
1173
p1.Table = T;
1174
1175
Eval4InputsFloat(Input + 1, Tmp2, &p1);
1176
1177
for (i=0; i < p -> nOutputs; i++) {
1178
1179
cmsFloat32Number y0 = Tmp1[i];
1180
cmsFloat32Number y1 = Tmp2[i];
1181
1182
Output[i] = y0 + (y1 - y0) * rest;
1183
}
1184
}
1185
1186
1187
1188
static CMS_NO_SANITIZE
1189
void Eval6Inputs(CMSREGISTER const cmsUInt16Number Input[],
1190
CMSREGISTER cmsUInt16Number Output[],
1191
CMSREGISTER const cmsInterpParams* p16)
1192
{
1193
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1194
cmsS15Fixed16Number fk;
1195
cmsS15Fixed16Number k0, rk;
1196
int K0, K1;
1197
const cmsUInt16Number* T;
1198
cmsUInt32Number i;
1199
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1200
cmsInterpParams p1;
1201
1202
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1203
k0 = FIXED_TO_INT(fk);
1204
rk = FIXED_REST_TO_INT(fk);
1205
1206
K0 = p16 -> opta[5] * k0;
1207
K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1208
1209
p1 = *p16;
1210
memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
1211
1212
T = LutTable + K0;
1213
p1.Table = T;
1214
1215
Eval5Inputs(Input + 1, Tmp1, &p1);
1216
1217
T = LutTable + K1;
1218
p1.Table = T;
1219
1220
Eval5Inputs(Input + 1, Tmp2, &p1);
1221
1222
for (i=0; i < p16 -> nOutputs; i++) {
1223
1224
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1225
}
1226
1227
}
1228
1229
1230
static
1231
void Eval6InputsFloat(const cmsFloat32Number Input[],
1232
cmsFloat32Number Output[],
1233
const cmsInterpParams* p)
1234
{
1235
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1236
cmsFloat32Number rest;
1237
cmsFloat32Number pk;
1238
int k0, K0, K1;
1239
const cmsFloat32Number* T;
1240
cmsUInt32Number i;
1241
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1242
cmsInterpParams p1;
1243
1244
pk = fclamp(Input[0]) * p->Domain[0];
1245
k0 = _cmsQuickFloor(pk);
1246
rest = pk - (cmsFloat32Number) k0;
1247
1248
K0 = p -> opta[5] * k0;
1249
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
1250
1251
p1 = *p;
1252
memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
1253
1254
T = LutTable + K0;
1255
p1.Table = T;
1256
1257
Eval5InputsFloat(Input + 1, Tmp1, &p1);
1258
1259
T = LutTable + K1;
1260
p1.Table = T;
1261
1262
Eval5InputsFloat(Input + 1, Tmp2, &p1);
1263
1264
for (i=0; i < p -> nOutputs; i++) {
1265
1266
cmsFloat32Number y0 = Tmp1[i];
1267
cmsFloat32Number y1 = Tmp2[i];
1268
1269
Output[i] = y0 + (y1 - y0) * rest;
1270
}
1271
}
1272
1273
1274
static CMS_NO_SANITIZE
1275
void Eval7Inputs(CMSREGISTER const cmsUInt16Number Input[],
1276
CMSREGISTER cmsUInt16Number Output[],
1277
CMSREGISTER const cmsInterpParams* p16)
1278
{
1279
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1280
cmsS15Fixed16Number fk;
1281
cmsS15Fixed16Number k0, rk;
1282
int K0, K1;
1283
const cmsUInt16Number* T;
1284
cmsUInt32Number i;
1285
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1286
cmsInterpParams p1;
1287
1288
1289
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1290
k0 = FIXED_TO_INT(fk);
1291
rk = FIXED_REST_TO_INT(fk);
1292
1293
K0 = p16 -> opta[6] * k0;
1294
K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1295
1296
p1 = *p16;
1297
memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
1298
1299
T = LutTable + K0;
1300
p1.Table = T;
1301
1302
Eval6Inputs(Input + 1, Tmp1, &p1);
1303
1304
T = LutTable + K1;
1305
p1.Table = T;
1306
1307
Eval6Inputs(Input + 1, Tmp2, &p1);
1308
1309
for (i=0; i < p16 -> nOutputs; i++) {
1310
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1311
}
1312
}
1313
1314
1315
static
1316
void Eval7InputsFloat(const cmsFloat32Number Input[],
1317
cmsFloat32Number Output[],
1318
const cmsInterpParams* p)
1319
{
1320
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1321
cmsFloat32Number rest;
1322
cmsFloat32Number pk;
1323
int k0, K0, K1;
1324
const cmsFloat32Number* T;
1325
cmsUInt32Number i;
1326
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1327
cmsInterpParams p1;
1328
1329
pk = fclamp(Input[0]) * p->Domain[0];
1330
k0 = _cmsQuickFloor(pk);
1331
rest = pk - (cmsFloat32Number) k0;
1332
1333
K0 = p -> opta[6] * k0;
1334
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
1335
1336
p1 = *p;
1337
memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
1338
1339
T = LutTable + K0;
1340
p1.Table = T;
1341
1342
Eval6InputsFloat(Input + 1, Tmp1, &p1);
1343
1344
T = LutTable + K1;
1345
p1.Table = T;
1346
1347
Eval6InputsFloat(Input + 1, Tmp2, &p1);
1348
1349
1350
for (i=0; i < p -> nOutputs; i++) {
1351
1352
cmsFloat32Number y0 = Tmp1[i];
1353
cmsFloat32Number y1 = Tmp2[i];
1354
1355
Output[i] = y0 + (y1 - y0) * rest;
1356
1357
}
1358
}
1359
1360
static CMS_NO_SANITIZE
1361
void Eval8Inputs(CMSREGISTER const cmsUInt16Number Input[],
1362
CMSREGISTER cmsUInt16Number Output[],
1363
CMSREGISTER const cmsInterpParams* p16)
1364
{
1365
const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1366
cmsS15Fixed16Number fk;
1367
cmsS15Fixed16Number k0, rk;
1368
int K0, K1;
1369
const cmsUInt16Number* T;
1370
cmsUInt32Number i;
1371
cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1372
cmsInterpParams p1;
1373
1374
fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1375
k0 = FIXED_TO_INT(fk);
1376
rk = FIXED_REST_TO_INT(fk);
1377
1378
K0 = p16 -> opta[7] * k0;
1379
K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1380
1381
p1 = *p16;
1382
memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
1383
1384
T = LutTable + K0;
1385
p1.Table = T;
1386
1387
Eval7Inputs(Input + 1, Tmp1, &p1);
1388
1389
T = LutTable + K1;
1390
p1.Table = T;
1391
Eval7Inputs(Input + 1, Tmp2, &p1);
1392
1393
for (i=0; i < p16 -> nOutputs; i++) {
1394
Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1395
}
1396
}
1397
1398
1399
1400
static
1401
void Eval8InputsFloat(const cmsFloat32Number Input[],
1402
cmsFloat32Number Output[],
1403
const cmsInterpParams* p)
1404
{
1405
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1406
cmsFloat32Number rest;
1407
cmsFloat32Number pk;
1408
int k0, K0, K1;
1409
const cmsFloat32Number* T;
1410
cmsUInt32Number i;
1411
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1412
cmsInterpParams p1;
1413
1414
pk = fclamp(Input[0]) * p->Domain[0];
1415
k0 = _cmsQuickFloor(pk);
1416
rest = pk - (cmsFloat32Number) k0;
1417
1418
K0 = p -> opta[7] * k0;
1419
K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
1420
1421
p1 = *p;
1422
memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
1423
1424
T = LutTable + K0;
1425
p1.Table = T;
1426
1427
Eval7InputsFloat(Input + 1, Tmp1, &p1);
1428
1429
T = LutTable + K1;
1430
p1.Table = T;
1431
1432
Eval7InputsFloat(Input + 1, Tmp2, &p1);
1433
1434
1435
for (i=0; i < p -> nOutputs; i++) {
1436
1437
cmsFloat32Number y0 = Tmp1[i];
1438
cmsFloat32Number y1 = Tmp2[i];
1439
1440
Output[i] = y0 + (y1 - y0) * rest;
1441
}
1442
}
1443
1444
// The default factory
1445
static
1446
cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
1447
{
1448
1449
cmsInterpFunction Interpolation;
1450
cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
1451
cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
1452
1453
memset(&Interpolation, 0, sizeof(Interpolation));
1454
1455
// Safety check
1456
if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
1457
return Interpolation;
1458
1459
switch (nInputChannels) {
1460
1461
case 1: // Gray LUT / linear
1462
1463
if (nOutputChannels == 1) {
1464
1465
if (IsFloat)
1466
Interpolation.LerpFloat = LinLerp1Dfloat;
1467
else
1468
Interpolation.Lerp16 = LinLerp1D;
1469
1470
}
1471
else {
1472
1473
if (IsFloat)
1474
Interpolation.LerpFloat = Eval1InputFloat;
1475
else
1476
Interpolation.Lerp16 = Eval1Input;
1477
}
1478
break;
1479
1480
case 2: // Duotone
1481
if (IsFloat)
1482
Interpolation.LerpFloat = BilinearInterpFloat;
1483
else
1484
Interpolation.Lerp16 = BilinearInterp16;
1485
break;
1486
1487
case 3: // RGB et al
1488
1489
if (IsTrilinear) {
1490
1491
if (IsFloat)
1492
Interpolation.LerpFloat = TrilinearInterpFloat;
1493
else
1494
Interpolation.Lerp16 = TrilinearInterp16;
1495
}
1496
else {
1497
1498
if (IsFloat)
1499
Interpolation.LerpFloat = TetrahedralInterpFloat;
1500
else {
1501
1502
Interpolation.Lerp16 = TetrahedralInterp16;
1503
}
1504
}
1505
break;
1506
1507
case 4: // CMYK lut
1508
1509
if (IsFloat)
1510
Interpolation.LerpFloat = Eval4InputsFloat;
1511
else
1512
Interpolation.Lerp16 = Eval4Inputs;
1513
break;
1514
1515
case 5: // 5 Inks
1516
if (IsFloat)
1517
Interpolation.LerpFloat = Eval5InputsFloat;
1518
else
1519
Interpolation.Lerp16 = Eval5Inputs;
1520
break;
1521
1522
case 6: // 6 Inks
1523
if (IsFloat)
1524
Interpolation.LerpFloat = Eval6InputsFloat;
1525
else
1526
Interpolation.Lerp16 = Eval6Inputs;
1527
break;
1528
1529
case 7: // 7 inks
1530
if (IsFloat)
1531
Interpolation.LerpFloat = Eval7InputsFloat;
1532
else
1533
Interpolation.Lerp16 = Eval7Inputs;
1534
break;
1535
1536
case 8: // 8 inks
1537
if (IsFloat)
1538
Interpolation.LerpFloat = Eval8InputsFloat;
1539
else
1540
Interpolation.Lerp16 = Eval8Inputs;
1541
break;
1542
1543
break;
1544
1545
default:
1546
Interpolation.Lerp16 = NULL;
1547
}
1548
1549
return Interpolation;
1550
}
1551
1552