cmsintrp.c 44.9 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25 26 27 28 29
 */

// This file is available under and governed by the GNU General Public
// License version 2 only, as published by the Free Software Foundation.
// However, the following notice accompanied the original version of this
// file:
//
30
//---------------------------------------------------------------------------------
D
duke 已提交
31
//
32
//  Little Color Management System
P
prr 已提交
33
//  Copyright (c) 1998-2017 Marti Maria Saguer
D
duke 已提交
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the Software
// is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 53 54 55 56 57
//
//---------------------------------------------------------------------------------
//

#include "lcms2_internal.h"

B
bae 已提交
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
D
duke 已提交
60

P
prr 已提交
61 62 63 64 65 66 67
// Some people may want to compile as C++ with all warnings on, in this case make compiler silent
#ifdef _MSC_VER
#    if (_MSC_VER >= 1400)
#       pragma warning( disable : 4365 )
#    endif
#endif

68 69
// Interpolation routines by default
static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
D
duke 已提交
70

71
// This is the default factory
P
prr 已提交
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
_cmsInterpPluginChunkType _cmsInterpPluginChunk = { NULL };

// The interpolation plug-in memory chunk allocator/dup
void _cmsAllocInterpPluginChunk(struct _cmsContext_struct* ctx, const struct _cmsContext_struct* src)
{
    void* from;

    _cmsAssert(ctx != NULL);

    if (src != NULL) {
        from = src ->chunks[InterpPlugin];
    }
    else {
        static _cmsInterpPluginChunkType InterpPluginChunk = { NULL };

        from = &InterpPluginChunk;
    }

    _cmsAssert(from != NULL);
    ctx ->chunks[InterpPlugin] = _cmsSubAllocDup(ctx ->MemPool, from, sizeof(_cmsInterpPluginChunkType));
}
D
duke 已提交
93

94 95

// Main plug-in entry
P
prr 已提交
96
cmsBool  _cmsRegisterInterpPlugin(cmsContext ContextID, cmsPluginBase* Data)
D
duke 已提交
97
{
98
    cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
P
prr 已提交
99
    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);
D
duke 已提交
100

101
    if (Data == NULL) {
D
duke 已提交
102

P
prr 已提交
103
        ptr ->Interpolators = NULL;
104 105
        return TRUE;
    }
D
duke 已提交
106

107
    // Set replacement functions
P
prr 已提交
108
    ptr ->Interpolators = Plugin ->InterpolatorsFactory;
109 110
    return TRUE;
}
D
duke 已提交
111 112


113
// Set the interpolation method
P
prr 已提交
114
cmsBool _cmsSetInterpolationRoutine(cmsContext ContextID, cmsInterpParams* p)
D
duke 已提交
115
{
P
prr 已提交
116 117 118 119 120 121 122
    _cmsInterpPluginChunkType* ptr = (_cmsInterpPluginChunkType*) _cmsContextGetClientChunk(ContextID, InterpPlugin);

    p ->Interpolation.Lerp16 = NULL;

   // Invoke factory, possibly in the Plug-in
    if (ptr ->Interpolators != NULL)
        p ->Interpolation = ptr->Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
D
duke 已提交
123

124 125 126 127
    // If unsupported by the plug-in, go for the LittleCMS default.
    // If happens only if an extern plug-in is being used
    if (p ->Interpolation.Lerp16 == NULL)
        p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
D
duke 已提交
128

129 130 131 132
    // Check for valid interpolator (we just check one member of the union)
    if (p ->Interpolation.Lerp16 == NULL) {
            return FALSE;
    }
P
prr 已提交
133

134 135
    return TRUE;
}
D
duke 已提交
136 137


138 139 140
// This function precalculates as many parameters as possible to speed up the interpolation.
cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
                                           const cmsUInt32Number nSamples[],
P
prr 已提交
141
                                           cmsUInt32Number InputChan, cmsUInt32Number OutputChan,
142 143 144 145
                                           const void *Table,
                                           cmsUInt32Number dwFlags)
{
    cmsInterpParams* p;
P
prr 已提交
146
    cmsUInt32Number i;
D
duke 已提交
147

148 149 150 151 152
    // Check for maximum inputs
    if (InputChan > MAX_INPUT_DIMENSIONS) {
             cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
            return NULL;
    }
D
duke 已提交
153

154 155 156
    // Creates an empty object
    p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
    if (p == NULL) return NULL;
D
duke 已提交
157

158 159 160 161 162 163
    // Keep original parameters
    p -> dwFlags  = dwFlags;
    p -> nInputs  = InputChan;
    p -> nOutputs = OutputChan;
    p ->Table     = Table;
    p ->ContextID  = ContextID;
D
duke 已提交
164

165 166
    // Fill samples per input direction and domain (which is number of nodes minus one)
    for (i=0; i < InputChan; i++) {
D
duke 已提交
167

168 169 170
        p -> nSamples[i] = nSamples[i];
        p -> Domain[i]   = nSamples[i] - 1;
    }
D
duke 已提交
171

172 173 174 175
    // Compute factors to apply to each component to index the grid array
    p -> opta[0] = p -> nOutputs;
    for (i=1; i < InputChan; i++)
        p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
D
duke 已提交
176 177


P
prr 已提交
178
    if (!_cmsSetInterpolationRoutine(ContextID, p)) {
179 180 181 182
         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
        _cmsFree(ContextID, p);
        return NULL;
    }
D
duke 已提交
183

184 185 186
    // All seems ok
    return p;
}
D
duke 已提交
187 188


189
// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
P
prr 已提交
190 191
cmsInterpParams* CMSEXPORT _cmsComputeInterpParams(cmsContext ContextID, cmsUInt32Number nSamples,
                                                   cmsUInt32Number InputChan, cmsUInt32Number OutputChan, const void* Table, cmsUInt32Number dwFlags)
192 193 194
{
    int i;
    cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
D
duke 已提交
195

196
    // Fill the auxiliary array
197 198
    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
        Samples[i] = nSamples;
D
duke 已提交
199

200 201 202
    // Call the extended function
    return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
}
D
duke 已提交
203 204


205
// Free all associated memory
P
prr 已提交
206
void CMSEXPORT _cmsFreeInterpParams(cmsInterpParams* p)
207 208 209
{
    if (p != NULL) _cmsFree(p ->ContextID, p);
}
D
duke 已提交
210 211


212 213 214 215 216 217
// Inline fixed point interpolation
cmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
{
    cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
    dif = (dif >> 16) + l;
    return (cmsUInt16Number) (dif);
D
duke 已提交
218 219 220
}


221
//  Linear interpolation (Fixed-point optimized)
D
duke 已提交
222
static
223 224 225
void LinLerp1D(register const cmsUInt16Number Value[],
               register cmsUInt16Number Output[],
               register const cmsInterpParams* p)
D
duke 已提交
226
{
227 228 229 230
    cmsUInt16Number y1, y0;
    int cell0, rest;
    int val3;
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
D
duke 已提交
231

232 233
    // if last value...
    if (Value[0] == 0xffff) {
D
duke 已提交
234

235 236 237
        Output[0] = LutTable[p -> Domain[0]];
        return;
    }
D
duke 已提交
238

239 240
    val3 = p -> Domain[0] * Value[0];
    val3 = _cmsToFixedDomain(val3);    // To fixed 15.16
D
duke 已提交
241

242 243
    cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
    rest  = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
D
duke 已提交
244

245 246
    y0 = LutTable[cell0];
    y1 = LutTable[cell0+1];
D
duke 已提交
247 248


249 250
    Output[0] = LinearInterp(rest, y0, y1);
}
D
duke 已提交
251

B
bae 已提交
252 253 254
// To prevent out of bounds indexing
cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v)
{
P
prr 已提交
255
    return ((v < 1.0e-9f) || isnan(v)) ? 0.0f : (v > 1.0f ? 1.0f : v);
B
bae 已提交
256
}
D
duke 已提交
257

258 259 260 261 262 263 264 265 266 267
// Floating-point version of 1D interpolation
static
void LinLerp1Dfloat(const cmsFloat32Number Value[],
                    cmsFloat32Number Output[],
                    const cmsInterpParams* p)
{
       cmsFloat32Number y1, y0;
       cmsFloat32Number val2, rest;
       int cell0, cell1;
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
D
duke 已提交
268

B
bae 已提交
269 270
       val2 = fclamp(Value[0]);

271
       // if last value...
B
bae 已提交
272
       if (val2 == 1.0) {
273 274
           Output[0] = LutTable[p -> Domain[0]];
           return;
D
duke 已提交
275 276
       }

B
bae 已提交
277
       val2 *= p -> Domain[0];
278 279 280 281 282 283 284 285 286 287 288

       cell0 = (int) floor(val2);
       cell1 = (int) ceil(val2);

       // Rest is 16 LSB bits
       rest = val2 - cell0;

       y0 = LutTable[cell0] ;
       y1 = LutTable[cell1] ;

       Output[0] = y0 + (y1 - y0) * rest;
D
duke 已提交
289 290 291
}


292 293

// Eval gray LUT having only one input channel
D
duke 已提交
294
static
295 296 297
void Eval1Input(register const cmsUInt16Number Input[],
                register cmsUInt16Number Output[],
                register const cmsInterpParams* p16)
D
duke 已提交
298
{
299 300 301 302 303
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, k1, rk, K0, K1;
       int v;
       cmsUInt32Number OutChan;
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
D
duke 已提交
304

305 306
       v = Input[0] * p16 -> Domain[0];
       fk = _cmsToFixedDomain(v);
D
duke 已提交
307 308

       k0 = FIXED_TO_INT(fk);
309
       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
D
duke 已提交
310

311
       k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
D
duke 已提交
312

313 314
       K0 = p16 -> opta[0] * k0;
       K1 = p16 -> opta[0] * k1;
D
duke 已提交
315

316
       for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
D
duke 已提交
317

318 319 320
           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
       }
}
D
duke 已提交
321 322 323



324 325 326 327 328 329 330 331 332 333 334 335
// Eval gray LUT having only one input channel
static
void Eval1InputFloat(const cmsFloat32Number Value[],
                     cmsFloat32Number Output[],
                     const cmsInterpParams* p)
{
    cmsFloat32Number y1, y0;
    cmsFloat32Number val2, rest;
    int cell0, cell1;
    cmsUInt32Number OutChan;
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;

B
bae 已提交
336 337
    val2 = fclamp(Value[0]);

338
        // if last value...
B
bae 已提交
339
       if (val2 == 1.0) {
340 341
           Output[0] = LutTable[p -> Domain[0]];
           return;
D
duke 已提交
342 343
       }

B
bae 已提交
344
       val2 *= p -> Domain[0];
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361

       cell0 = (int) floor(val2);
       cell1 = (int) ceil(val2);

       // Rest is 16 LSB bits
       rest = val2 - cell0;

       cell0 *= p -> opta[0];
       cell1 *= p -> opta[0];

       for (OutChan=0; OutChan < p->nOutputs; OutChan++) {

            y0 = LutTable[cell0 + OutChan] ;
            y1 = LutTable[cell1 + OutChan] ;

            Output[OutChan] = y0 + (y1 - y0) * rest;
       }
D
duke 已提交
362 363
}

B
bae 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
// Bilinear interpolation (16 bits) - cmsFloat32Number version
static
void BilinearInterpFloat(const cmsFloat32Number Input[],
                         cmsFloat32Number Output[],
                         const cmsInterpParams* p)

{
#   define LERP(a,l,h)    (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
#   define DENS(i,j)      (LutTable[(i)+(j)+OutChan])

    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
    cmsFloat32Number      px, py;
    int        x0, y0,
               X0, Y0, X1, Y1;
    int        TotalOut, OutChan;
    cmsFloat32Number      fx, fy,
        d00, d01, d10, d11,
        dx0, dx1,
        dxy;

    TotalOut   = p -> nOutputs;
B
bae 已提交
385 386
    px = fclamp(Input[0]) * p->Domain[0];
    py = fclamp(Input[1]) * p->Domain[1];
B
bae 已提交
387 388 389 390 391

    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;

    X0 = p -> opta[1] * x0;
P
prr 已提交
392
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[1]);
B
bae 已提交
393 394

    Y0 = p -> opta[0] * y0;
P
prr 已提交
395
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[0]);
B
bae 已提交
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473

    for (OutChan = 0; OutChan < TotalOut; OutChan++) {

        d00 = DENS(X0, Y0);
        d01 = DENS(X0, Y1);
        d10 = DENS(X1, Y0);
        d11 = DENS(X1, Y1);

        dx0 = LERP(fx, d00, d10);
        dx1 = LERP(fx, d01, d11);

        dxy = LERP(fy, dx0, dx1);

        Output[OutChan] = dxy;
    }


#   undef LERP
#   undef DENS
}

// Bilinear interpolation (16 bits) - optimized version
static
void BilinearInterp16(register const cmsUInt16Number Input[],
                      register cmsUInt16Number Output[],
                      register const cmsInterpParams* p)

{
#define DENS(i,j) (LutTable[(i)+(j)+OutChan])
#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))

           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
           int        OutChan, TotalOut;
           cmsS15Fixed16Number    fx, fy;
  register int        rx, ry;
           int        x0, y0;
  register int        X0, X1, Y0, Y1;
           int        d00, d01, d10, d11,
                      dx0, dx1,
                      dxy;

    TotalOut   = p -> nOutputs;

    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
    x0  = FIXED_TO_INT(fx);
    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain


    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
    y0  = FIXED_TO_INT(fy);
    ry  = FIXED_REST_TO_INT(fy);


    X0 = p -> opta[1] * x0;
    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);

    Y0 = p -> opta[0] * y0;
    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);

    for (OutChan = 0; OutChan < TotalOut; OutChan++) {

        d00 = DENS(X0, Y0);
        d01 = DENS(X0, Y1);
        d10 = DENS(X1, Y0);
        d11 = DENS(X1, Y1);

        dx0 = LERP(rx, d00, d10);
        dx1 = LERP(rx, d01, d11);

        dxy = LERP(ry, dx0, dx1);

        Output[OutChan] = (cmsUInt16Number) dxy;
    }


#   undef LERP
#   undef DENS
}
474 475 476


// Trilinear interpolation (16 bits) - cmsFloat32Number version
D
duke 已提交
477
static
478 479 480 481
void TrilinearInterpFloat(const cmsFloat32Number Input[],
                          cmsFloat32Number Output[],
                          const cmsInterpParams* p)

D
duke 已提交
482
{
483 484
#   define LERP(a,l,h)      (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
#   define DENS(i,j,k)      (LutTable[(i)+(j)+(k)+OutChan])
D
duke 已提交
485

486 487 488 489 490 491 492 493 494 495
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
    cmsFloat32Number      px, py, pz;
    int        x0, y0, z0,
               X0, Y0, Z0, X1, Y1, Z1;
    int        TotalOut, OutChan;
    cmsFloat32Number      fx, fy, fz,
        d000, d001, d010, d011,
        d100, d101, d110, d111,
        dx00, dx01, dx10, dx11,
        dxy0, dxy1, dxyz;
D
duke 已提交
496

497
    TotalOut   = p -> nOutputs;
D
duke 已提交
498

B
bae 已提交
499
    // We need some clipping here
B
bae 已提交
500 501 502
    px = fclamp(Input[0]) * p->Domain[0];
    py = fclamp(Input[1]) * p->Domain[1];
    pz = fclamp(Input[2]) * p->Domain[2];
D
duke 已提交
503

P
prr 已提交
504 505 506
    x0 = (int) floor(px); fx = px - (cmsFloat32Number) x0;  // We need full floor funcionality here
    y0 = (int) floor(py); fy = py - (cmsFloat32Number) y0;
    z0 = (int) floor(pz); fz = pz - (cmsFloat32Number) z0;
D
duke 已提交
507

508
    X0 = p -> opta[2] * x0;
P
prr 已提交
509
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
D
duke 已提交
510

511
    Y0 = p -> opta[1] * y0;
P
prr 已提交
512
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
D
duke 已提交
513

514
    Z0 = p -> opta[0] * z0;
P
prr 已提交
515
    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
D
duke 已提交
516

517
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
D
duke 已提交
518

519 520 521 522
        d000 = DENS(X0, Y0, Z0);
        d001 = DENS(X0, Y0, Z1);
        d010 = DENS(X0, Y1, Z0);
        d011 = DENS(X0, Y1, Z1);
D
duke 已提交
523

524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545
        d100 = DENS(X1, Y0, Z0);
        d101 = DENS(X1, Y0, Z1);
        d110 = DENS(X1, Y1, Z0);
        d111 = DENS(X1, Y1, Z1);


        dx00 = LERP(fx, d000, d100);
        dx01 = LERP(fx, d001, d101);
        dx10 = LERP(fx, d010, d110);
        dx11 = LERP(fx, d011, d111);

        dxy0 = LERP(fy, dx00, dx10);
        dxy1 = LERP(fy, dx01, dx11);

        dxyz = LERP(fz, dxy0, dxy1);

        Output[OutChan] = dxyz;
    }


#   undef LERP
#   undef DENS
D
duke 已提交
546 547
}

548
// Trilinear interpolation (16 bits) - optimized version
D
duke 已提交
549
static
550 551 552
void TrilinearInterp16(register const cmsUInt16Number Input[],
                       register cmsUInt16Number Output[],
                       register const cmsInterpParams* p)
D
duke 已提交
553

554 555 556
{
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
#define LERP(a,l,h)     (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
D
duke 已提交
557

558 559 560 561 562 563 564 565 566 567
           const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
           int        OutChan, TotalOut;
           cmsS15Fixed16Number    fx, fy, fz;
  register int        rx, ry, rz;
           int        x0, y0, z0;
  register int        X0, X1, Y0, Y1, Z0, Z1;
           int        d000, d001, d010, d011,
                      d100, d101, d110, d111,
                      dx00, dx01, dx10, dx11,
                      dxy0, dxy1, dxyz;
D
duke 已提交
568

569
    TotalOut   = p -> nOutputs;
D
duke 已提交
570

571 572 573
    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
    x0  = FIXED_TO_INT(fx);
    rx  = FIXED_REST_TO_INT(fx);    // Rest in 0..1.0 domain
D
duke 已提交
574 575


576 577 578
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
    y0  = FIXED_TO_INT(fy);
    ry  = FIXED_REST_TO_INT(fy);
D
duke 已提交
579

580 581 582
    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
    z0 = FIXED_TO_INT(fz);
    rz = FIXED_REST_TO_INT(fz);
D
duke 已提交
583 584


585 586
    X0 = p -> opta[2] * x0;
    X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
D
duke 已提交
587

588 589
    Y0 = p -> opta[1] * y0;
    Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
D
duke 已提交
590

591 592
    Z0 = p -> opta[0] * z0;
    Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
D
duke 已提交
593

594
    for (OutChan = 0; OutChan < TotalOut; OutChan++) {
D
duke 已提交
595

596 597 598 599
        d000 = DENS(X0, Y0, Z0);
        d001 = DENS(X0, Y0, Z1);
        d010 = DENS(X0, Y1, Z0);
        d011 = DENS(X0, Y1, Z1);
D
duke 已提交
600

601 602 603 604
        d100 = DENS(X1, Y0, Z0);
        d101 = DENS(X1, Y0, Z1);
        d110 = DENS(X1, Y1, Z0);
        d111 = DENS(X1, Y1, Z1);
D
duke 已提交
605 606


607 608 609 610
        dx00 = LERP(rx, d000, d100);
        dx01 = LERP(rx, d001, d101);
        dx10 = LERP(rx, d010, d110);
        dx11 = LERP(rx, d011, d111);
D
duke 已提交
611

612 613
        dxy0 = LERP(ry, dx00, dx10);
        dxy1 = LERP(ry, dx01, dx11);
D
duke 已提交
614

615
        dxyz = LERP(rz, dxy0, dxy1);
D
duke 已提交
616

617 618
        Output[OutChan] = (cmsUInt16Number) dxyz;
    }
D
duke 已提交
619 620


621 622 623
#   undef LERP
#   undef DENS
}
D
duke 已提交
624 625


626 627 628 629 630 631 632 633 634 635 636 637 638 639
// Tetrahedral interpolation, using Sakamoto algorithm.
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
static
void TetrahedralInterpFloat(const cmsFloat32Number Input[],
                            cmsFloat32Number Output[],
                            const cmsInterpParams* p)
{
    const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
    cmsFloat32Number     px, py, pz;
    int        x0, y0, z0,
               X0, Y0, Z0, X1, Y1, Z1;
    cmsFloat32Number     rx, ry, rz;
    cmsFloat32Number     c0, c1=0, c2=0, c3=0;
    int                  OutChan, TotalOut;
D
duke 已提交
640

641
    TotalOut   = p -> nOutputs;
D
duke 已提交
642

B
bae 已提交
643
    // We need some clipping here
B
bae 已提交
644 645 646
    px = fclamp(Input[0]) * p->Domain[0];
    py = fclamp(Input[1]) * p->Domain[1];
    pz = fclamp(Input[2]) * p->Domain[2];
D
duke 已提交
647

P
prr 已提交
648 649 650
    x0 = (int) floor(px); rx = (px - (cmsFloat32Number) x0);  // We need full floor functionality here
    y0 = (int) floor(py); ry = (py - (cmsFloat32Number) y0);
    z0 = (int) floor(pz); rz = (pz - (cmsFloat32Number) z0);
D
duke 已提交
651 652


653
    X0 = p -> opta[2] * x0;
P
prr 已提交
654
    X1 = X0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[2]);
D
duke 已提交
655

656
    Y0 = p -> opta[1] * y0;
P
prr 已提交
657
    Y1 = Y0 + (fclamp(Input[1]) >= 1.0 ? 0 : p->opta[1]);
D
duke 已提交
658

659
    Z0 = p -> opta[0] * z0;
P
prr 已提交
660
    Z1 = Z0 + (fclamp(Input[2]) >= 1.0 ? 0 : p->opta[0]);
D
duke 已提交
661

662
    for (OutChan=0; OutChan < TotalOut; OutChan++) {
D
duke 已提交
663

664
       // These are the 6 Tetrahedral
D
duke 已提交
665

666
        c0 = DENS(X0, Y0, Z0);
D
duke 已提交
667

668
        if (rx >= ry && ry >= rz) {
D
duke 已提交
669

670 671 672
            c1 = DENS(X1, Y0, Z0) - c0;
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
673

674 675 676
        }
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
677

678 679 680
                c1 = DENS(X1, Y0, Z0) - c0;
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
D
duke 已提交
681

682 683 684
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
685

686 687 688
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                    c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
689

690 691 692
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
693

694 695 696
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
                        c2 = DENS(X0, Y1, Z0) - c0;
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
697

698 699 700
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
701

702 703 704
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                            c2 = DENS(X0, Y1, Z0) - c0;
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
D
duke 已提交
705

706 707 708
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
709

710 711 712
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
                                c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
713

714 715 716 717
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
718

719 720
       Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
       }
D
duke 已提交
721 722 723

}

724
#undef DENS
D
duke 已提交
725 726 727 728




729 730 731 732
static
void TetrahedralInterp16(register const cmsUInt16Number Input[],
                         register cmsUInt16Number Output[],
                         register const cmsInterpParams* p)
D
duke 已提交
733
{
734
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
B
bae 已提交
735 736 737 738 739 740
    cmsS15Fixed16Number fx, fy, fz;
    cmsS15Fixed16Number rx, ry, rz;
    int x0, y0, z0;
    cmsS15Fixed16Number c0, c1, c2, c3, Rest;
    cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
    cmsUInt32Number TotalOut = p -> nOutputs;
D
duke 已提交
741

B
bae 已提交
742 743 744
    fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
D
duke 已提交
745

B
bae 已提交
746 747 748
    x0 = FIXED_TO_INT(fx);
    y0 = FIXED_TO_INT(fy);
    z0 = FIXED_TO_INT(fz);
D
duke 已提交
749

B
bae 已提交
750 751 752
    rx = FIXED_REST_TO_INT(fx);
    ry = FIXED_REST_TO_INT(fy);
    rz = FIXED_REST_TO_INT(fz);
D
duke 已提交
753

754
    X0 = p -> opta[2] * x0;
B
bae 已提交
755
    X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
D
duke 已提交
756

757
    Y0 = p -> opta[1] * y0;
B
bae 已提交
758
    Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
D
duke 已提交
759

760
    Z0 = p -> opta[0] * z0;
B
bae 已提交
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
    Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);

    LutTable = &LutTable[X0+Y0+Z0];

    // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
    // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
    // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
    // at the cost of being off by one at 7fff and 17ffe.

    if (rx >= ry) {
        if (ry >= rz) {
            Y1 += X1;
            Z1 += Y1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c3 -= c2;
                c2 -= c1;
                c1 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
            }
        } else if (rz >= rx) {
            X1 += Z1;
            Y1 += X1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c2 -= c1;
                c1 -= c3;
                c3 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
            }
        } else {
            Z1 += X1;
            Y1 += Z1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c2 -= c3;
                c3 -= c1;
                c1 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
            }
813
        }
B
bae 已提交
814 815 816 817 818 819 820 821 822 823 824 825 826 827
    } else {
        if (rx >= rz) {
            X1 += Y1;
            Z1 += X1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c3 -= c1;
                c1 -= c2;
                c2 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
828
            }
B
bae 已提交
829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
        } else if (ry >= rz) {
            Z1 += Y1;
            X1 += Z1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c1 -= c3;
                c3 -= c2;
                c2 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
            }
        } else {
            Y1 += Z1;
            X1 += Y1;
            for (; TotalOut; TotalOut--) {
                c1 = LutTable[X1];
                c2 = LutTable[Y1];
                c3 = LutTable[Z1];
                c0 = *LutTable++;
                c1 -= c2;
                c2 -= c3;
                c3 -= c0;
                Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
            }
        }
858
    }
D
duke 已提交
859 860 861
}


862 863 864 865 866
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
static
void Eval4Inputs(register const cmsUInt16Number Input[],
                     register cmsUInt16Number Output[],
                     register const cmsInterpParams* p16)
D
duke 已提交
867
{
P
prr 已提交
868
    const cmsUInt16Number* LutTable;
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890
    cmsS15Fixed16Number fk;
    cmsS15Fixed16Number k0, rk;
    int K0, K1;
    cmsS15Fixed16Number    fx, fy, fz;
    cmsS15Fixed16Number    rx, ry, rz;
    int                    x0, y0, z0;
    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
    cmsUInt32Number i;
    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
    cmsUInt32Number        OutChan;
    cmsUInt16Number        Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];


    fk  = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
    fx  = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
    fy  = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
    fz  = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);

    k0  = FIXED_TO_INT(fk);
    x0  = FIXED_TO_INT(fx);
    y0  = FIXED_TO_INT(fy);
    z0  = FIXED_TO_INT(fz);
D
duke 已提交
891

892 893 894 895
    rk  = FIXED_REST_TO_INT(fk);
    rx  = FIXED_REST_TO_INT(fx);
    ry  = FIXED_REST_TO_INT(fy);
    rz  = FIXED_REST_TO_INT(fz);
D
duke 已提交
896

897 898
    K0 = p16 -> opta[3] * k0;
    K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
D
duke 已提交
899

900 901
    X0 = p16 -> opta[2] * x0;
    X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
D
duke 已提交
902

903 904
    Y0 = p16 -> opta[1] * y0;
    Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
D
duke 已提交
905

906 907
    Z0 = p16 -> opta[0] * z0;
    Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
D
duke 已提交
908

909 910
    LutTable = (cmsUInt16Number*) p16 -> Table;
    LutTable += K0;
D
duke 已提交
911

912
    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
D
duke 已提交
913

914 915 916 917 918 919 920
        c0 = DENS(X0, Y0, Z0);

        if (rx >= ry && ry >= rz) {

            c1 = DENS(X1, Y0, Z0) - c0;
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
921 922

        }
923 924
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
925

926 927 928
                c1 = DENS(X1, Y0, Z0) - c0;
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
D
duke 已提交
929

930 931 932
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
933

934 935 936
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                    c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
937

938 939 940
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
941

942 943 944
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
                        c2 = DENS(X0, Y1, Z0) - c0;
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
945

946 947 948
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
949

950 951 952
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                            c2 = DENS(X0, Y1, Z0) - c0;
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
D
duke 已提交
953

954 955 956
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
957

958 959 960
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
                                c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
961

962
                            }
P
prr 已提交
963
                            else {
964 965
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
966

967
                            Rest = c1 * rx + c2 * ry + c3 * rz;
D
duke 已提交
968

P
prr 已提交
969
                            Tmp1[OutChan] = (cmsUInt16Number)(c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
970
    }
D
duke 已提交
971 972


973 974
    LutTable = (cmsUInt16Number*) p16 -> Table;
    LutTable += K1;
D
duke 已提交
975

976
    for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
D
duke 已提交
977

978
        c0 = DENS(X0, Y0, Z0);
D
duke 已提交
979

980
        if (rx >= ry && ry >= rz) {
D
duke 已提交
981

982 983 984
            c1 = DENS(X1, Y0, Z0) - c0;
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
985

986 987 988
        }
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
989

990 991 992
                c1 = DENS(X1, Y0, Z0) - c0;
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
D
duke 已提交
993

994 995 996
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
997

998 999 1000
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                    c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
1001

1002 1003 1004
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
1005

1006 1007 1008
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
                        c2 = DENS(X0, Y1, Z0) - c0;
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
D
duke 已提交
1009

1010 1011 1012
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
1013

1014 1015 1016
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                            c2 = DENS(X0, Y1, Z0) - c0;
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
D
duke 已提交
1017

1018 1019 1020
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
1021

1022 1023 1024
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
                                c3 = DENS(X0, Y0, Z1) - c0;
D
duke 已提交
1025

1026 1027 1028 1029
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
1030

1031
                            Rest = c1 * rx + c2 * ry + c3 * rz;
D
duke 已提交
1032

P
prr 已提交
1033
                            Tmp2[OutChan] = (cmsUInt16Number) (c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest)));
1034
    }
D
duke 已提交
1035 1036 1037



1038 1039 1040 1041 1042
    for (i=0; i < p16 -> nOutputs; i++) {
        Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    }
}
#undef DENS
D
duke 已提交
1043 1044


1045 1046
// For more that 3 inputs (i.e., CMYK)
// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
D
duke 已提交
1047 1048


1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
static
void Eval4InputsFloat(const cmsFloat32Number Input[],
                      cmsFloat32Number Output[],
                      const cmsInterpParams* p)
{
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
       cmsFloat32Number rest;
       cmsFloat32Number pk;
       int k0, K0, K1;
       const cmsFloat32Number* T;
       cmsUInt32Number i;
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1062

B
bae 已提交
1063
       pk = fclamp(Input[0]) * p->Domain[0];
1064 1065
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1066

1067
       K0 = p -> opta[3] * k0;
P
prr 已提交
1068
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[3]);
D
duke 已提交
1069

1070 1071
       p1 = *p;
       memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
D
duke 已提交
1072

1073 1074
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1075

1076
       TetrahedralInterpFloat(Input + 1,  Tmp1, &p1);
D
duke 已提交
1077

1078 1079 1080
       T = LutTable + K1;
       p1.Table = T;
       TetrahedralInterpFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1081

1082 1083 1084 1085
       for (i=0; i < p -> nOutputs; i++)
       {
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];
D
duke 已提交
1086

1087 1088 1089
              Output[i] = y0 + (y1 - y0) * rest;
       }
}
D
duke 已提交
1090 1091


1092 1093 1094
static
void Eval5Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
D
duke 已提交
1095

1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
                 register const cmsInterpParams* p16)
{
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, rk;
       int K0, K1;
       const cmsUInt16Number* T;
       cmsUInt32Number i;
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1106 1107


1108 1109 1110
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1111

1112 1113
       K0 = p16 -> opta[4] * k0;
       K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
D
duke 已提交
1114

1115 1116
       p1 = *p16;
       memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
D
duke 已提交
1117

1118 1119
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1120

1121
       Eval4Inputs(Input + 1, Tmp1, &p1);
D
duke 已提交
1122

1123 1124
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1125

1126
       Eval4Inputs(Input + 1, Tmp2, &p1);
D
duke 已提交
1127

1128
       for (i=0; i < p16 -> nOutputs; i++) {
D
duke 已提交
1129

1130 1131
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
D
duke 已提交
1132

1133
}
D
duke 已提交
1134 1135


1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
static
void Eval5InputsFloat(const cmsFloat32Number Input[],
                      cmsFloat32Number Output[],
                      const cmsInterpParams* p)
{
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
       cmsFloat32Number rest;
       cmsFloat32Number pk;
       int k0, K0, K1;
       const cmsFloat32Number* T;
       cmsUInt32Number i;
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1149

B
bae 已提交
1150
       pk = fclamp(Input[0]) * p->Domain[0];
1151 1152
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1153

1154
       K0 = p -> opta[4] * k0;
P
prr 已提交
1155
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[4]);
D
duke 已提交
1156

1157 1158
       p1 = *p;
       memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
D
duke 已提交
1159

1160 1161
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1162

1163
       Eval4InputsFloat(Input + 1,  Tmp1, &p1);
D
duke 已提交
1164

1165 1166
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1167

1168
       Eval4InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1169

1170 1171 1172 1173 1174 1175 1176
       for (i=0; i < p -> nOutputs; i++) {

              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];

              Output[i] = y0 + (y1 - y0) * rest;
       }
D
duke 已提交
1177 1178 1179 1180
}



1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
static
void Eval6Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
                 register const cmsInterpParams* p16)
{
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, rk;
       int K0, K1;
       const cmsUInt16Number* T;
       cmsUInt32Number i;
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1194

1195 1196 1197
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1198

1199 1200
       K0 = p16 -> opta[5] * k0;
       K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
D
duke 已提交
1201

1202 1203
       p1 = *p16;
       memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
D
duke 已提交
1204

1205 1206
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1207

1208
       Eval5Inputs(Input + 1, Tmp1, &p1);
D
duke 已提交
1209

1210 1211
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1212

1213
       Eval5Inputs(Input + 1, Tmp2, &p1);
D
duke 已提交
1214

1215
       for (i=0; i < p16 -> nOutputs; i++) {
D
duke 已提交
1216

1217 1218
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
D
duke 已提交
1219

1220
}
D
duke 已提交
1221 1222


1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
static
void Eval6InputsFloat(const cmsFloat32Number Input[],
                      cmsFloat32Number Output[],
                      const cmsInterpParams* p)
{
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
       cmsFloat32Number rest;
       cmsFloat32Number pk;
       int k0, K0, K1;
       const cmsFloat32Number* T;
       cmsUInt32Number i;
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1236

B
bae 已提交
1237
       pk = fclamp(Input[0]) * p->Domain[0];
1238 1239
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1240

1241
       K0 = p -> opta[5] * k0;
P
prr 已提交
1242
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[5]);
D
duke 已提交
1243

1244 1245
       p1 = *p;
       memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
D
duke 已提交
1246

1247 1248
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1249

1250
       Eval5InputsFloat(Input + 1,  Tmp1, &p1);
D
duke 已提交
1251

1252 1253
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1254

1255
       Eval5InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1256

1257
       for (i=0; i < p -> nOutputs; i++) {
D
duke 已提交
1258

1259 1260
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];
D
duke 已提交
1261

1262 1263 1264
              Output[i] = y0 + (y1 - y0) * rest;
       }
}
D
duke 已提交
1265 1266


1267 1268 1269 1270
static
void Eval7Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
                 register const cmsInterpParams* p16)
D
duke 已提交
1271
{
1272 1273 1274 1275 1276 1277 1278 1279
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, rk;
       int K0, K1;
       const cmsUInt16Number* T;
       cmsUInt32Number i;
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1280 1281


1282 1283 1284
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1285

1286 1287
       K0 = p16 -> opta[6] * k0;
       K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
D
duke 已提交
1288

1289
       p1 = *p16;
B
bae 已提交
1290
       memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
D
duke 已提交
1291

1292 1293
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1294

1295
       Eval6Inputs(Input + 1, Tmp1, &p1);
D
duke 已提交
1296

1297 1298
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1299

1300
       Eval6Inputs(Input + 1, Tmp2, &p1);
D
duke 已提交
1301

1302 1303 1304 1305
       for (i=0; i < p16 -> nOutputs; i++) {
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
}
D
duke 已提交
1306 1307


1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
static
void Eval7InputsFloat(const cmsFloat32Number Input[],
                      cmsFloat32Number Output[],
                      const cmsInterpParams* p)
{
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
       cmsFloat32Number rest;
       cmsFloat32Number pk;
       int k0, K0, K1;
       const cmsFloat32Number* T;
       cmsUInt32Number i;
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1321

B
bae 已提交
1322
       pk = fclamp(Input[0]) * p->Domain[0];
1323 1324
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1325

1326
       K0 = p -> opta[6] * k0;
P
prr 已提交
1327
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[6]);
D
duke 已提交
1328

1329 1330
       p1 = *p;
       memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
D
duke 已提交
1331

1332 1333
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1334

1335
       Eval6InputsFloat(Input + 1,  Tmp1, &p1);
D
duke 已提交
1336

1337 1338
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1339

1340
       Eval6InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1341 1342


1343 1344 1345 1346
       for (i=0; i < p -> nOutputs; i++) {

              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];
D
duke 已提交
1347

1348
              Output[i] = y0 + (y1 - y0) * rest;
D
duke 已提交
1349 1350

       }
1351
}
D
duke 已提交
1352

1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365
static
void Eval8Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
                 register const cmsInterpParams* p16)
{
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, rk;
       int K0, K1;
       const cmsUInt16Number* T;
       cmsUInt32Number i;
       cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1366

1367 1368 1369
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1370

1371 1372
       K0 = p16 -> opta[7] * k0;
       K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
D
duke 已提交
1373

1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
       p1 = *p16;
       memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));

       T = LutTable + K0;
       p1.Table = T;

       Eval7Inputs(Input + 1, Tmp1, &p1);

       T = LutTable + K1;
       p1.Table = T;
       Eval7Inputs(Input + 1, Tmp2, &p1);

       for (i=0; i < p16 -> nOutputs; i++) {
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
D
duke 已提交
1388
       }
1389
}
D
duke 已提交
1390 1391 1392



1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
static
void Eval8InputsFloat(const cmsFloat32Number Input[],
                      cmsFloat32Number Output[],
                      const cmsInterpParams* p)
{
       const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
       cmsFloat32Number rest;
       cmsFloat32Number pk;
       int k0, K0, K1;
       const cmsFloat32Number* T;
       cmsUInt32Number i;
       cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
       cmsInterpParams p1;
D
duke 已提交
1406

B
bae 已提交
1407
       pk = fclamp(Input[0]) * p->Domain[0];
1408 1409
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1410

1411
       K0 = p -> opta[7] * k0;
P
prr 已提交
1412
       K1 = K0 + (fclamp(Input[0]) >= 1.0 ? 0 : p->opta[7]);
1413 1414 1415

       p1 = *p;
       memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
D
duke 已提交
1416

1417 1418
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1419

1420
       Eval7InputsFloat(Input + 1,  Tmp1, &p1);
D
duke 已提交
1421

1422 1423
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1424

1425
       Eval7InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1426 1427


1428
       for (i=0; i < p -> nOutputs; i++) {
D
duke 已提交
1429

1430 1431 1432 1433 1434 1435
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];

              Output[i] = y0 + (y1 - y0) * rest;
       }
}
D
duke 已提交
1436

1437 1438 1439
// The default factory
static
cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
D
duke 已提交
1440 1441
{

1442 1443 1444
    cmsInterpFunction Interpolation;
    cmsBool  IsFloat     = (dwFlags & CMS_LERP_FLAGS_FLOAT);
    cmsBool  IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
D
duke 已提交
1445

1446
    memset(&Interpolation, 0, sizeof(Interpolation));
D
duke 已提交
1447

1448 1449 1450
    // Safety check
    if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
        return Interpolation;
D
duke 已提交
1451

1452
    switch (nInputChannels) {
D
duke 已提交
1453

1454
           case 1: // Gray LUT / linear
D
duke 已提交
1455

1456
               if (nOutputChannels == 1) {
D
duke 已提交
1457

1458 1459 1460 1461
                   if (IsFloat)
                       Interpolation.LerpFloat = LinLerp1Dfloat;
                   else
                       Interpolation.Lerp16 = LinLerp1D;
D
duke 已提交
1462

1463 1464
               }
               else {
D
duke 已提交
1465

1466 1467 1468 1469 1470 1471
                   if (IsFloat)
                       Interpolation.LerpFloat = Eval1InputFloat;
                   else
                       Interpolation.Lerp16 = Eval1Input;
               }
               break;
D
duke 已提交
1472

B
bae 已提交
1473 1474 1475 1476 1477 1478
           case 2: // Duotone
               if (IsFloat)
                      Interpolation.LerpFloat =  BilinearInterpFloat;
               else
                      Interpolation.Lerp16    =  BilinearInterp16;
               break;
D
duke 已提交
1479

1480
           case 3:  // RGB et al
D
duke 已提交
1481

1482
               if (IsTrilinear) {
D
duke 已提交
1483

1484 1485 1486 1487 1488 1489
                   if (IsFloat)
                       Interpolation.LerpFloat = TrilinearInterpFloat;
                   else
                       Interpolation.Lerp16 = TrilinearInterp16;
               }
               else {
D
duke 已提交
1490

1491 1492 1493
                   if (IsFloat)
                       Interpolation.LerpFloat = TetrahedralInterpFloat;
                   else {
D
duke 已提交
1494

1495 1496 1497 1498
                       Interpolation.Lerp16 = TetrahedralInterp16;
                   }
               }
               break;
D
duke 已提交
1499

1500
           case 4:  // CMYK lut
D
duke 已提交
1501

1502 1503 1504 1505 1506
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval4InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval4Inputs;
               break;
D
duke 已提交
1507

1508 1509 1510 1511 1512 1513
           case 5: // 5 Inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval5InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval5Inputs;
               break;
D
duke 已提交
1514

1515 1516 1517 1518 1519 1520
           case 6: // 6 Inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval6InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval6Inputs;
               break;
D
duke 已提交
1521

1522 1523 1524 1525 1526 1527
           case 7: // 7 inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval7InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval7Inputs;
               break;
D
duke 已提交
1528

1529 1530 1531 1532 1533 1534
           case 8: // 8 inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval8InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval8Inputs;
               break;
D
duke 已提交
1535

1536
               break;
D
duke 已提交
1537

1538 1539
           default:
               Interpolation.Lerp16 = NULL;
D
duke 已提交
1540 1541
    }

1542
    return Interpolation;
D
duke 已提交
1543
}