Merged-in libcms2 v2.5
[AROS.git] / workbench / libs / lcms2 / src / cmsintrp.c
blobea33cc6cf01b858aee3658088c02d4e7aea4d8b7
1 //---------------------------------------------------------------------------------
2 //
3 // Little Color Management System
4 // Copyright (c) 1998-2012 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:
13 // The above copyright notice and this permission notice shall be included in
14 // all copies or substantial portions of the Software.
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.
24 //---------------------------------------------------------------------------------
27 #include "lcms2_internal.h"
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
32 // Interpolation routines by default
33 static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
35 // This is the default factory
36 static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
39 // Main plug-in entry
40 cmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
42 cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
44 if (Data == NULL) {
46 Interpolators = DefaultInterpolatorsFactory;
47 return TRUE;
50 // Set replacement functions
51 Interpolators = Plugin ->InterpolatorsFactory;
52 return TRUE;
56 // Set the interpolation method
57 cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
59 // Invoke factory, possibly in the Plug-in
60 p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
62 // If unsupported by the plug-in, go for the LittleCMS default.
63 // If happens only if an extern plug-in is being used
64 if (p ->Interpolation.Lerp16 == NULL)
65 p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
67 // Check for valid interpolator (we just check one member of the union)
68 if (p ->Interpolation.Lerp16 == NULL) {
69 return FALSE;
71 return TRUE;
75 // This function precalculates as many parameters as possible to speed up the interpolation.
76 cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
77 const cmsUInt32Number nSamples[],
78 int InputChan, int OutputChan,
79 const void *Table,
80 cmsUInt32Number dwFlags)
82 cmsInterpParams* p;
83 int i;
85 // Check for maximum inputs
86 if (InputChan > MAX_INPUT_DIMENSIONS) {
87 cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
88 return NULL;
91 // Creates an empty object
92 p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
93 if (p == NULL) return NULL;
95 // Keep original parameters
96 p -> dwFlags = dwFlags;
97 p -> nInputs = InputChan;
98 p -> nOutputs = OutputChan;
99 p ->Table = Table;
100 p ->ContextID = ContextID;
102 // Fill samples per input direction and domain (which is number of nodes minus one)
103 for (i=0; i < InputChan; i++) {
105 p -> nSamples[i] = nSamples[i];
106 p -> Domain[i] = nSamples[i] - 1;
109 // Compute factors to apply to each component to index the grid array
110 p -> opta[0] = p -> nOutputs;
111 for (i=1; i < InputChan; i++)
112 p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
115 if (!_cmsSetInterpolationRoutine(p)) {
116 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
117 _cmsFree(ContextID, p);
118 return NULL;
121 // All seems ok
122 return p;
126 // This one is a wrapper on the anterior, but assuming all directions have same number of nodes
127 cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
129 int i;
130 cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
132 // Fill the auxiliar array
133 for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
134 Samples[i] = nSamples;
136 // Call the extended function
137 return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
141 // Free all associated memory
142 void _cmsFreeInterpParams(cmsInterpParams* p)
144 if (p != NULL) _cmsFree(p ->ContextID, p);
148 // Inline fixed point interpolation
149 cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
151 cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
152 dif = (dif >> 16) + l;
153 return (cmsUInt16Number) (dif);
157 // Linear interpolation (Fixed-point optimized)
158 static
159 void LinLerp1D(register const cmsUInt16Number Value[],
160 register cmsUInt16Number Output[],
161 register const cmsInterpParams* p)
163 cmsUInt16Number y1, y0;
164 int cell0, rest;
165 int val3;
166 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
168 // if last value...
169 if (Value[0] == 0xffff) {
171 Output[0] = LutTable[p -> Domain[0]];
172 return;
175 val3 = p -> Domain[0] * Value[0];
176 val3 = _cmsToFixedDomain(val3); // To fixed 15.16
178 cell0 = FIXED_TO_INT(val3); // Cell is 16 MSB bits
179 rest = FIXED_REST_TO_INT(val3); // Rest is 16 LSB bits
181 y0 = LutTable[cell0];
182 y1 = LutTable[cell0+1];
185 Output[0] = LinearInterp(rest, y0, y1);
189 // Floating-point version of 1D interpolation
190 static
191 void LinLerp1Dfloat(const cmsFloat32Number Value[],
192 cmsFloat32Number Output[],
193 const cmsInterpParams* p)
195 cmsFloat32Number y1, y0;
196 cmsFloat32Number val2, rest;
197 int cell0, cell1;
198 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
200 // if last value...
201 if (Value[0] == 1.0) {
202 Output[0] = LutTable[p -> Domain[0]];
203 return;
206 val2 = p -> Domain[0] * Value[0];
208 cell0 = (int) floor(val2);
209 cell1 = (int) ceil(val2);
211 // Rest is 16 LSB bits
212 rest = val2 - cell0;
214 y0 = LutTable[cell0] ;
215 y1 = LutTable[cell1] ;
217 Output[0] = y0 + (y1 - y0) * rest;
222 // Eval gray LUT having only one input channel
223 static
224 void Eval1Input(register const cmsUInt16Number Input[],
225 register cmsUInt16Number Output[],
226 register const cmsInterpParams* p16)
228 cmsS15Fixed16Number fk;
229 cmsS15Fixed16Number k0, k1, rk, K0, K1;
230 int v;
231 cmsUInt32Number OutChan;
232 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
234 v = Input[0] * p16 -> Domain[0];
235 fk = _cmsToFixedDomain(v);
237 k0 = FIXED_TO_INT(fk);
238 rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
240 k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
242 K0 = p16 -> opta[0] * k0;
243 K1 = p16 -> opta[0] * k1;
245 for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
247 Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
253 // Eval gray LUT having only one input channel
254 static
255 void Eval1InputFloat(const cmsFloat32Number Value[],
256 cmsFloat32Number Output[],
257 const cmsInterpParams* p)
259 cmsFloat32Number y1, y0;
260 cmsFloat32Number val2, rest;
261 int cell0, cell1;
262 cmsUInt32Number OutChan;
263 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
265 // if last value...
266 if (Value[0] == 1.0) {
267 Output[0] = LutTable[p -> Domain[0]];
268 return;
271 val2 = p -> Domain[0] * Value[0];
273 cell0 = (int) floor(val2);
274 cell1 = (int) ceil(val2);
276 // Rest is 16 LSB bits
277 rest = val2 - cell0;
279 cell0 *= p -> opta[0];
280 cell1 *= p -> opta[0];
282 for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
284 y0 = LutTable[cell0 + OutChan] ;
285 y1 = LutTable[cell1 + OutChan] ;
287 Output[OutChan] = y0 + (y1 - y0) * rest;
291 // Bilinear interpolation (16 bits) - cmsFloat32Number version
292 static
293 void BilinearInterpFloat(const cmsFloat32Number Input[],
294 cmsFloat32Number Output[],
295 const cmsInterpParams* p)
298 # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
299 # define DENS(i,j) (LutTable[(i)+(j)+OutChan])
301 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
302 cmsFloat32Number px, py;
303 int x0, y0,
304 X0, Y0, X1, Y1;
305 int TotalOut, OutChan;
306 cmsFloat32Number fx, fy,
307 d00, d01, d10, d11,
308 dx0, dx1,
309 dxy;
311 TotalOut = p -> nOutputs;
312 px = Input[0] * p->Domain[0];
313 py = Input[1] * p->Domain[1];
315 x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
316 y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
318 X0 = p -> opta[1] * x0;
319 X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
321 Y0 = p -> opta[0] * y0;
322 Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
324 for (OutChan = 0; OutChan < TotalOut; OutChan++) {
326 d00 = DENS(X0, Y0);
327 d01 = DENS(X0, Y1);
328 d10 = DENS(X1, Y0);
329 d11 = DENS(X1, Y1);
331 dx0 = LERP(fx, d00, d10);
332 dx1 = LERP(fx, d01, d11);
334 dxy = LERP(fy, dx0, dx1);
336 Output[OutChan] = dxy;
340 # undef LERP
341 # undef DENS
344 // Bilinear interpolation (16 bits) - optimized version
345 static
346 void BilinearInterp16(register const cmsUInt16Number Input[],
347 register cmsUInt16Number Output[],
348 register const cmsInterpParams* p)
351 #define DENS(i,j) (LutTable[(i)+(j)+OutChan])
352 #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
354 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
355 int OutChan, TotalOut;
356 cmsS15Fixed16Number fx, fy;
357 register int rx, ry;
358 int x0, y0;
359 register int X0, X1, Y0, Y1;
360 int d00, d01, d10, d11,
361 dx0, dx1,
362 dxy;
364 TotalOut = p -> nOutputs;
366 fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
367 x0 = FIXED_TO_INT(fx);
368 rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
371 fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
372 y0 = FIXED_TO_INT(fy);
373 ry = FIXED_REST_TO_INT(fy);
376 X0 = p -> opta[1] * x0;
377 X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
379 Y0 = p -> opta[0] * y0;
380 Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
382 for (OutChan = 0; OutChan < TotalOut; OutChan++) {
384 d00 = DENS(X0, Y0);
385 d01 = DENS(X0, Y1);
386 d10 = DENS(X1, Y0);
387 d11 = DENS(X1, Y1);
389 dx0 = LERP(rx, d00, d10);
390 dx1 = LERP(rx, d01, d11);
392 dxy = LERP(ry, dx0, dx1);
394 Output[OutChan] = (cmsUInt16Number) dxy;
398 # undef LERP
399 # undef DENS
403 // Trilinear interpolation (16 bits) - cmsFloat32Number version
404 static
405 void TrilinearInterpFloat(const cmsFloat32Number Input[],
406 cmsFloat32Number Output[],
407 const cmsInterpParams* p)
410 # define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
411 # define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
413 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
414 cmsFloat32Number px, py, pz;
415 int x0, y0, z0,
416 X0, Y0, Z0, X1, Y1, Z1;
417 int TotalOut, OutChan;
418 cmsFloat32Number fx, fy, fz,
419 d000, d001, d010, d011,
420 d100, d101, d110, d111,
421 dx00, dx01, dx10, dx11,
422 dxy0, dxy1, dxyz;
424 TotalOut = p -> nOutputs;
426 // We need some clipping here
427 px = Input[0];
428 py = Input[1];
429 pz = Input[2];
431 if (px < 0) px = 0;
432 if (px > 1) px = 1;
433 if (py < 0) py = 0;
434 if (py > 1) py = 1;
435 if (pz < 0) pz = 0;
436 if (pz > 1) pz = 1;
438 px *= p->Domain[0];
439 py *= p->Domain[1];
440 pz *= p->Domain[2];
442 x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
443 y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
444 z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
446 X0 = p -> opta[2] * x0;
447 X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
449 Y0 = p -> opta[1] * y0;
450 Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
452 Z0 = p -> opta[0] * z0;
453 Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
455 for (OutChan = 0; OutChan < TotalOut; OutChan++) {
457 d000 = DENS(X0, Y0, Z0);
458 d001 = DENS(X0, Y0, Z1);
459 d010 = DENS(X0, Y1, Z0);
460 d011 = DENS(X0, Y1, Z1);
462 d100 = DENS(X1, Y0, Z0);
463 d101 = DENS(X1, Y0, Z1);
464 d110 = DENS(X1, Y1, Z0);
465 d111 = DENS(X1, Y1, Z1);
468 dx00 = LERP(fx, d000, d100);
469 dx01 = LERP(fx, d001, d101);
470 dx10 = LERP(fx, d010, d110);
471 dx11 = LERP(fx, d011, d111);
473 dxy0 = LERP(fy, dx00, dx10);
474 dxy1 = LERP(fy, dx01, dx11);
476 dxyz = LERP(fz, dxy0, dxy1);
478 Output[OutChan] = dxyz;
482 # undef LERP
483 # undef DENS
486 // Trilinear interpolation (16 bits) - optimized version
487 static
488 void TrilinearInterp16(register const cmsUInt16Number Input[],
489 register cmsUInt16Number Output[],
490 register const cmsInterpParams* p)
493 #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
494 #define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
496 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
497 int OutChan, TotalOut;
498 cmsS15Fixed16Number fx, fy, fz;
499 register int rx, ry, rz;
500 int x0, y0, z0;
501 register int X0, X1, Y0, Y1, Z0, Z1;
502 int d000, d001, d010, d011,
503 d100, d101, d110, d111,
504 dx00, dx01, dx10, dx11,
505 dxy0, dxy1, dxyz;
507 TotalOut = p -> nOutputs;
509 fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
510 x0 = FIXED_TO_INT(fx);
511 rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
514 fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
515 y0 = FIXED_TO_INT(fy);
516 ry = FIXED_REST_TO_INT(fy);
518 fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
519 z0 = FIXED_TO_INT(fz);
520 rz = FIXED_REST_TO_INT(fz);
523 X0 = p -> opta[2] * x0;
524 X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
526 Y0 = p -> opta[1] * y0;
527 Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
529 Z0 = p -> opta[0] * z0;
530 Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
532 for (OutChan = 0; OutChan < TotalOut; OutChan++) {
534 d000 = DENS(X0, Y0, Z0);
535 d001 = DENS(X0, Y0, Z1);
536 d010 = DENS(X0, Y1, Z0);
537 d011 = DENS(X0, Y1, Z1);
539 d100 = DENS(X1, Y0, Z0);
540 d101 = DENS(X1, Y0, Z1);
541 d110 = DENS(X1, Y1, Z0);
542 d111 = DENS(X1, Y1, Z1);
545 dx00 = LERP(rx, d000, d100);
546 dx01 = LERP(rx, d001, d101);
547 dx10 = LERP(rx, d010, d110);
548 dx11 = LERP(rx, d011, d111);
550 dxy0 = LERP(ry, dx00, dx10);
551 dxy1 = LERP(ry, dx01, dx11);
553 dxyz = LERP(rz, dxy0, dxy1);
555 Output[OutChan] = (cmsUInt16Number) dxyz;
559 # undef LERP
560 # undef DENS
564 // Tetrahedral interpolation, using Sakamoto algorithm.
565 #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
566 static
567 void TetrahedralInterpFloat(const cmsFloat32Number Input[],
568 cmsFloat32Number Output[],
569 const cmsInterpParams* p)
571 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
572 cmsFloat32Number px, py, pz;
573 int x0, y0, z0,
574 X0, Y0, Z0, X1, Y1, Z1;
575 cmsFloat32Number rx, ry, rz;
576 cmsFloat32Number c0, c1=0, c2=0, c3=0;
577 int OutChan, TotalOut;
579 TotalOut = p -> nOutputs;
581 // We need some clipping here
582 px = Input[0];
583 py = Input[1];
584 pz = Input[2];
586 if (px < 0) px = 0;
587 if (px > 1) px = 1;
588 if (py < 0) py = 0;
589 if (py > 1) py = 1;
590 if (pz < 0) pz = 0;
591 if (pz > 1) pz = 1;
593 px *= p->Domain[0];
594 py *= p->Domain[1];
595 pz *= p->Domain[2];
597 x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
598 y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
599 z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
602 X0 = p -> opta[2] * x0;
603 X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
605 Y0 = p -> opta[1] * y0;
606 Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
608 Z0 = p -> opta[0] * z0;
609 Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
611 for (OutChan=0; OutChan < TotalOut; OutChan++) {
613 // These are the 6 Tetrahedral
615 c0 = DENS(X0, Y0, Z0);
617 if (rx >= ry && ry >= rz) {
619 c1 = DENS(X1, Y0, Z0) - c0;
620 c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
621 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
624 else
625 if (rx >= rz && rz >= ry) {
627 c1 = DENS(X1, Y0, Z0) - c0;
628 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
629 c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
632 else
633 if (rz >= rx && rx >= ry) {
635 c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
636 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
637 c3 = DENS(X0, Y0, Z1) - c0;
640 else
641 if (ry >= rx && rx >= rz) {
643 c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
644 c2 = DENS(X0, Y1, Z0) - c0;
645 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
648 else
649 if (ry >= rz && rz >= rx) {
651 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
652 c2 = DENS(X0, Y1, Z0) - c0;
653 c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
656 else
657 if (rz >= ry && ry >= rx) {
659 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
660 c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
661 c3 = DENS(X0, Y0, Z1) - c0;
664 else {
665 c1 = c2 = c3 = 0;
668 Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
673 #undef DENS
678 static
679 void TetrahedralInterp16(register const cmsUInt16Number Input[],
680 register cmsUInt16Number Output[],
681 register const cmsInterpParams* p)
683 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
684 cmsS15Fixed16Number fx, fy, fz;
685 cmsS15Fixed16Number rx, ry, rz;
686 int x0, y0, z0;
687 cmsS15Fixed16Number c0, c1, c2, c3, Rest;
688 cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
689 cmsUInt32Number TotalOut = p -> nOutputs;
691 fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
692 fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
693 fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
695 x0 = FIXED_TO_INT(fx);
696 y0 = FIXED_TO_INT(fy);
697 z0 = FIXED_TO_INT(fz);
699 rx = FIXED_REST_TO_INT(fx);
700 ry = FIXED_REST_TO_INT(fy);
701 rz = FIXED_REST_TO_INT(fz);
703 X0 = p -> opta[2] * x0;
704 X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
706 Y0 = p -> opta[1] * y0;
707 Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
709 Z0 = p -> opta[0] * z0;
710 Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
712 LutTable = &LutTable[X0+Y0+Z0];
714 // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
715 // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
716 // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
717 // at the cost of being off by one at 7fff and 17ffe.
719 if (rx >= ry) {
720 if (ry >= rz) {
721 Y1 += X1;
722 Z1 += Y1;
723 for (; TotalOut; TotalOut--) {
724 c1 = LutTable[X1];
725 c2 = LutTable[Y1];
726 c3 = LutTable[Z1];
727 c0 = *LutTable++;
728 c3 -= c2;
729 c2 -= c1;
730 c1 -= c0;
731 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
732 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
734 } else if (rz >= rx) {
735 X1 += Z1;
736 Y1 += X1;
737 for (; TotalOut; TotalOut--) {
738 c1 = LutTable[X1];
739 c2 = LutTable[Y1];
740 c3 = LutTable[Z1];
741 c0 = *LutTable++;
742 c2 -= c1;
743 c1 -= c3;
744 c3 -= c0;
745 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
746 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
748 } else {
749 Z1 += X1;
750 Y1 += Z1;
751 for (; TotalOut; TotalOut--) {
752 c1 = LutTable[X1];
753 c2 = LutTable[Y1];
754 c3 = LutTable[Z1];
755 c0 = *LutTable++;
756 c2 -= c3;
757 c3 -= c1;
758 c1 -= c0;
759 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
760 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
763 } else {
764 if (rx >= rz) {
765 X1 += Y1;
766 Z1 += X1;
767 for (; TotalOut; TotalOut--) {
768 c1 = LutTable[X1];
769 c2 = LutTable[Y1];
770 c3 = LutTable[Z1];
771 c0 = *LutTable++;
772 c3 -= c1;
773 c1 -= c2;
774 c2 -= c0;
775 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
776 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
778 } else if (ry >= rz) {
779 Z1 += Y1;
780 X1 += Z1;
781 for (; TotalOut; TotalOut--) {
782 c1 = LutTable[X1];
783 c2 = LutTable[Y1];
784 c3 = LutTable[Z1];
785 c0 = *LutTable++;
786 c1 -= c3;
787 c3 -= c2;
788 c2 -= c0;
789 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
790 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
792 } else {
793 Y1 += Z1;
794 X1 += Y1;
795 for (; TotalOut; TotalOut--) {
796 c1 = LutTable[X1];
797 c2 = LutTable[Y1];
798 c3 = LutTable[Z1];
799 c0 = *LutTable++;
800 c1 -= c2;
801 c2 -= c3;
802 c3 -= c0;
803 Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
804 *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
811 #define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
812 static
813 void Eval4Inputs(register const cmsUInt16Number Input[],
814 register cmsUInt16Number Output[],
815 register const cmsInterpParams* p16)
817 const cmsUInt16Number* LutTable;
818 cmsS15Fixed16Number fk;
819 cmsS15Fixed16Number k0, rk;
820 int K0, K1;
821 cmsS15Fixed16Number fx, fy, fz;
822 cmsS15Fixed16Number rx, ry, rz;
823 int x0, y0, z0;
824 cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
825 cmsUInt32Number i;
826 cmsS15Fixed16Number c0, c1, c2, c3, Rest;
827 cmsUInt32Number OutChan;
828 cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
831 fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
832 fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
833 fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
834 fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
836 k0 = FIXED_TO_INT(fk);
837 x0 = FIXED_TO_INT(fx);
838 y0 = FIXED_TO_INT(fy);
839 z0 = FIXED_TO_INT(fz);
841 rk = FIXED_REST_TO_INT(fk);
842 rx = FIXED_REST_TO_INT(fx);
843 ry = FIXED_REST_TO_INT(fy);
844 rz = FIXED_REST_TO_INT(fz);
846 K0 = p16 -> opta[3] * k0;
847 K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
849 X0 = p16 -> opta[2] * x0;
850 X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
852 Y0 = p16 -> opta[1] * y0;
853 Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
855 Z0 = p16 -> opta[0] * z0;
856 Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
858 LutTable = (cmsUInt16Number*) p16 -> Table;
859 LutTable += K0;
861 for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
863 c0 = DENS(X0, Y0, Z0);
865 if (rx >= ry && ry >= rz) {
867 c1 = DENS(X1, Y0, Z0) - c0;
868 c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
869 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
872 else
873 if (rx >= rz && rz >= ry) {
875 c1 = DENS(X1, Y0, Z0) - c0;
876 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
877 c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
880 else
881 if (rz >= rx && rx >= ry) {
883 c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
884 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
885 c3 = DENS(X0, Y0, Z1) - c0;
888 else
889 if (ry >= rx && rx >= rz) {
891 c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
892 c2 = DENS(X0, Y1, Z0) - c0;
893 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
896 else
897 if (ry >= rz && rz >= rx) {
899 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
900 c2 = DENS(X0, Y1, Z0) - c0;
901 c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
904 else
905 if (rz >= ry && ry >= rx) {
907 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
908 c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
909 c3 = DENS(X0, Y0, Z1) - c0;
912 else {
913 c1 = c2 = c3 = 0;
916 Rest = c1 * rx + c2 * ry + c3 * rz;
918 Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
922 LutTable = (cmsUInt16Number*) p16 -> Table;
923 LutTable += K1;
925 for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
927 c0 = DENS(X0, Y0, Z0);
929 if (rx >= ry && ry >= rz) {
931 c1 = DENS(X1, Y0, Z0) - c0;
932 c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
933 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
936 else
937 if (rx >= rz && rz >= ry) {
939 c1 = DENS(X1, Y0, Z0) - c0;
940 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
941 c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
944 else
945 if (rz >= rx && rx >= ry) {
947 c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
948 c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
949 c3 = DENS(X0, Y0, Z1) - c0;
952 else
953 if (ry >= rx && rx >= rz) {
955 c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
956 c2 = DENS(X0, Y1, Z0) - c0;
957 c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
960 else
961 if (ry >= rz && rz >= rx) {
963 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
964 c2 = DENS(X0, Y1, Z0) - c0;
965 c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
968 else
969 if (rz >= ry && ry >= rx) {
971 c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
972 c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
973 c3 = DENS(X0, Y0, Z1) - c0;
976 else {
977 c1 = c2 = c3 = 0;
980 Rest = c1 * rx + c2 * ry + c3 * rz;
982 Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
987 for (i=0; i < p16 -> nOutputs; i++) {
988 Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
991 #undef DENS
994 // For more that 3 inputs (i.e., CMYK)
995 // evaluate two 3-dimensional interpolations and then linearly interpolate between them.
998 static
999 void Eval4InputsFloat(const cmsFloat32Number Input[],
1000 cmsFloat32Number Output[],
1001 const cmsInterpParams* p)
1003 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1004 cmsFloat32Number rest;
1005 cmsFloat32Number pk;
1006 int k0, K0, K1;
1007 const cmsFloat32Number* T;
1008 cmsUInt32Number i;
1009 cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1010 cmsInterpParams p1;
1013 pk = Input[0] * p->Domain[0];
1014 k0 = _cmsQuickFloor(pk);
1015 rest = pk - (cmsFloat32Number) k0;
1017 K0 = p -> opta[3] * k0;
1018 K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
1020 p1 = *p;
1021 memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
1023 T = LutTable + K0;
1024 p1.Table = T;
1026 TetrahedralInterpFloat(Input + 1, Tmp1, &p1);
1028 T = LutTable + K1;
1029 p1.Table = T;
1030 TetrahedralInterpFloat(Input + 1, Tmp2, &p1);
1032 for (i=0; i < p -> nOutputs; i++)
1034 cmsFloat32Number y0 = Tmp1[i];
1035 cmsFloat32Number y1 = Tmp2[i];
1037 Output[i] = y0 + (y1 - y0) * rest;
1042 static
1043 void Eval5Inputs(register const cmsUInt16Number Input[],
1044 register cmsUInt16Number Output[],
1046 register const cmsInterpParams* p16)
1048 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1049 cmsS15Fixed16Number fk;
1050 cmsS15Fixed16Number k0, rk;
1051 int K0, K1;
1052 const cmsUInt16Number* T;
1053 cmsUInt32Number i;
1054 cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1055 cmsInterpParams p1;
1058 fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1059 k0 = FIXED_TO_INT(fk);
1060 rk = FIXED_REST_TO_INT(fk);
1062 K0 = p16 -> opta[4] * k0;
1063 K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1065 p1 = *p16;
1066 memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
1068 T = LutTable + K0;
1069 p1.Table = T;
1071 Eval4Inputs(Input + 1, Tmp1, &p1);
1073 T = LutTable + K1;
1074 p1.Table = T;
1076 Eval4Inputs(Input + 1, Tmp2, &p1);
1078 for (i=0; i < p16 -> nOutputs; i++) {
1080 Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1086 static
1087 void Eval5InputsFloat(const cmsFloat32Number Input[],
1088 cmsFloat32Number Output[],
1089 const cmsInterpParams* p)
1091 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1092 cmsFloat32Number rest;
1093 cmsFloat32Number pk;
1094 int k0, K0, K1;
1095 const cmsFloat32Number* T;
1096 cmsUInt32Number i;
1097 cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1098 cmsInterpParams p1;
1100 pk = Input[0] * p->Domain[0];
1101 k0 = _cmsQuickFloor(pk);
1102 rest = pk - (cmsFloat32Number) k0;
1104 K0 = p -> opta[4] * k0;
1105 K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
1107 p1 = *p;
1108 memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
1110 T = LutTable + K0;
1111 p1.Table = T;
1113 Eval4InputsFloat(Input + 1, Tmp1, &p1);
1115 T = LutTable + K1;
1116 p1.Table = T;
1118 Eval4InputsFloat(Input + 1, Tmp2, &p1);
1120 for (i=0; i < p -> nOutputs; i++) {
1122 cmsFloat32Number y0 = Tmp1[i];
1123 cmsFloat32Number y1 = Tmp2[i];
1125 Output[i] = y0 + (y1 - y0) * rest;
1131 static
1132 void Eval6Inputs(register const cmsUInt16Number Input[],
1133 register cmsUInt16Number Output[],
1134 register const cmsInterpParams* p16)
1136 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1137 cmsS15Fixed16Number fk;
1138 cmsS15Fixed16Number k0, rk;
1139 int K0, K1;
1140 const cmsUInt16Number* T;
1141 cmsUInt32Number i;
1142 cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1143 cmsInterpParams p1;
1145 fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1146 k0 = FIXED_TO_INT(fk);
1147 rk = FIXED_REST_TO_INT(fk);
1149 K0 = p16 -> opta[5] * k0;
1150 K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1152 p1 = *p16;
1153 memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
1155 T = LutTable + K0;
1156 p1.Table = T;
1158 Eval5Inputs(Input + 1, Tmp1, &p1);
1160 T = LutTable + K1;
1161 p1.Table = T;
1163 Eval5Inputs(Input + 1, Tmp2, &p1);
1165 for (i=0; i < p16 -> nOutputs; i++) {
1167 Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1173 static
1174 void Eval6InputsFloat(const cmsFloat32Number Input[],
1175 cmsFloat32Number Output[],
1176 const cmsInterpParams* p)
1178 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1179 cmsFloat32Number rest;
1180 cmsFloat32Number pk;
1181 int k0, K0, K1;
1182 const cmsFloat32Number* T;
1183 cmsUInt32Number i;
1184 cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1185 cmsInterpParams p1;
1187 pk = Input[0] * p->Domain[0];
1188 k0 = _cmsQuickFloor(pk);
1189 rest = pk - (cmsFloat32Number) k0;
1191 K0 = p -> opta[5] * k0;
1192 K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
1194 p1 = *p;
1195 memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
1197 T = LutTable + K0;
1198 p1.Table = T;
1200 Eval5InputsFloat(Input + 1, Tmp1, &p1);
1202 T = LutTable + K1;
1203 p1.Table = T;
1205 Eval5InputsFloat(Input + 1, Tmp2, &p1);
1207 for (i=0; i < p -> nOutputs; i++) {
1209 cmsFloat32Number y0 = Tmp1[i];
1210 cmsFloat32Number y1 = Tmp2[i];
1212 Output[i] = y0 + (y1 - y0) * rest;
1217 static
1218 void Eval7Inputs(register const cmsUInt16Number Input[],
1219 register cmsUInt16Number Output[],
1220 register const cmsInterpParams* p16)
1222 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1223 cmsS15Fixed16Number fk;
1224 cmsS15Fixed16Number k0, rk;
1225 int K0, K1;
1226 const cmsUInt16Number* T;
1227 cmsUInt32Number i;
1228 cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1229 cmsInterpParams p1;
1232 fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1233 k0 = FIXED_TO_INT(fk);
1234 rk = FIXED_REST_TO_INT(fk);
1236 K0 = p16 -> opta[6] * k0;
1237 K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1239 p1 = *p16;
1240 memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
1242 T = LutTable + K0;
1243 p1.Table = T;
1245 Eval6Inputs(Input + 1, Tmp1, &p1);
1247 T = LutTable + K1;
1248 p1.Table = T;
1250 Eval6Inputs(Input + 1, Tmp2, &p1);
1252 for (i=0; i < p16 -> nOutputs; i++) {
1253 Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1258 static
1259 void Eval7InputsFloat(const cmsFloat32Number Input[],
1260 cmsFloat32Number Output[],
1261 const cmsInterpParams* p)
1263 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1264 cmsFloat32Number rest;
1265 cmsFloat32Number pk;
1266 int k0, K0, K1;
1267 const cmsFloat32Number* T;
1268 cmsUInt32Number i;
1269 cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1270 cmsInterpParams p1;
1272 pk = Input[0] * p->Domain[0];
1273 k0 = _cmsQuickFloor(pk);
1274 rest = pk - (cmsFloat32Number) k0;
1276 K0 = p -> opta[6] * k0;
1277 K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
1279 p1 = *p;
1280 memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
1282 T = LutTable + K0;
1283 p1.Table = T;
1285 Eval6InputsFloat(Input + 1, Tmp1, &p1);
1287 T = LutTable + K1;
1288 p1.Table = T;
1290 Eval6InputsFloat(Input + 1, Tmp2, &p1);
1293 for (i=0; i < p -> nOutputs; i++) {
1295 cmsFloat32Number y0 = Tmp1[i];
1296 cmsFloat32Number y1 = Tmp2[i];
1298 Output[i] = y0 + (y1 - y0) * rest;
1303 static
1304 void Eval8Inputs(register const cmsUInt16Number Input[],
1305 register cmsUInt16Number Output[],
1306 register const cmsInterpParams* p16)
1308 const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
1309 cmsS15Fixed16Number fk;
1310 cmsS15Fixed16Number k0, rk;
1311 int K0, K1;
1312 const cmsUInt16Number* T;
1313 cmsUInt32Number i;
1314 cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1315 cmsInterpParams p1;
1317 fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
1318 k0 = FIXED_TO_INT(fk);
1319 rk = FIXED_REST_TO_INT(fk);
1321 K0 = p16 -> opta[7] * k0;
1322 K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
1324 p1 = *p16;
1325 memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
1327 T = LutTable + K0;
1328 p1.Table = T;
1330 Eval7Inputs(Input + 1, Tmp1, &p1);
1332 T = LutTable + K1;
1333 p1.Table = T;
1334 Eval7Inputs(Input + 1, Tmp2, &p1);
1336 for (i=0; i < p16 -> nOutputs; i++) {
1337 Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
1343 static
1344 void Eval8InputsFloat(const cmsFloat32Number Input[],
1345 cmsFloat32Number Output[],
1346 const cmsInterpParams* p)
1348 const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
1349 cmsFloat32Number rest;
1350 cmsFloat32Number pk;
1351 int k0, K0, K1;
1352 const cmsFloat32Number* T;
1353 cmsUInt32Number i;
1354 cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
1355 cmsInterpParams p1;
1357 pk = Input[0] * p->Domain[0];
1358 k0 = _cmsQuickFloor(pk);
1359 rest = pk - (cmsFloat32Number) k0;
1361 K0 = p -> opta[7] * k0;
1362 K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
1364 p1 = *p;
1365 memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
1367 T = LutTable + K0;
1368 p1.Table = T;
1370 Eval7InputsFloat(Input + 1, Tmp1, &p1);
1372 T = LutTable + K1;
1373 p1.Table = T;
1375 Eval7InputsFloat(Input + 1, Tmp2, &p1);
1378 for (i=0; i < p -> nOutputs; i++) {
1380 cmsFloat32Number y0 = Tmp1[i];
1381 cmsFloat32Number y1 = Tmp2[i];
1383 Output[i] = y0 + (y1 - y0) * rest;
1387 // The default factory
1388 static
1389 cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
1392 cmsInterpFunction Interpolation;
1393 cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
1394 cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
1396 memset(&Interpolation, 0, sizeof(Interpolation));
1398 // Safety check
1399 if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
1400 return Interpolation;
1402 switch (nInputChannels) {
1404 case 1: // Gray LUT / linear
1406 if (nOutputChannels == 1) {
1408 if (IsFloat)
1409 Interpolation.LerpFloat = LinLerp1Dfloat;
1410 else
1411 Interpolation.Lerp16 = LinLerp1D;
1414 else {
1416 if (IsFloat)
1417 Interpolation.LerpFloat = Eval1InputFloat;
1418 else
1419 Interpolation.Lerp16 = Eval1Input;
1421 break;
1423 case 2: // Duotone
1424 if (IsFloat)
1425 Interpolation.LerpFloat = BilinearInterpFloat;
1426 else
1427 Interpolation.Lerp16 = BilinearInterp16;
1428 break;
1430 case 3: // RGB et al
1432 if (IsTrilinear) {
1434 if (IsFloat)
1435 Interpolation.LerpFloat = TrilinearInterpFloat;
1436 else
1437 Interpolation.Lerp16 = TrilinearInterp16;
1439 else {
1441 if (IsFloat)
1442 Interpolation.LerpFloat = TetrahedralInterpFloat;
1443 else {
1445 Interpolation.Lerp16 = TetrahedralInterp16;
1448 break;
1450 case 4: // CMYK lut
1452 if (IsFloat)
1453 Interpolation.LerpFloat = Eval4InputsFloat;
1454 else
1455 Interpolation.Lerp16 = Eval4Inputs;
1456 break;
1458 case 5: // 5 Inks
1459 if (IsFloat)
1460 Interpolation.LerpFloat = Eval5InputsFloat;
1461 else
1462 Interpolation.Lerp16 = Eval5Inputs;
1463 break;
1465 case 6: // 6 Inks
1466 if (IsFloat)
1467 Interpolation.LerpFloat = Eval6InputsFloat;
1468 else
1469 Interpolation.Lerp16 = Eval6Inputs;
1470 break;
1472 case 7: // 7 inks
1473 if (IsFloat)
1474 Interpolation.LerpFloat = Eval7InputsFloat;
1475 else
1476 Interpolation.Lerp16 = Eval7Inputs;
1477 break;
1479 case 8: // 8 inks
1480 if (IsFloat)
1481 Interpolation.LerpFloat = Eval8InputsFloat;
1482 else
1483 Interpolation.Lerp16 = Eval8Inputs;
1484 break;
1486 break;
1488 default:
1489 Interpolation.Lerp16 = NULL;
1492 return Interpolation;