cmsintrp.c 39.1 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 33
//  Little Color Management System
//  Copyright (c) 1998-2010 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 58 59
//
//---------------------------------------------------------------------------------
//

#include "lcms2_internal.h"

// This module incorporates several interpolation routines, for 1, 3, 4, 5, 6, 7 and 8 channels on input and
// up to 65535 channels on output. The user may change those by using the interpolation plug-in
D
duke 已提交
60

61 62
// Interpolation routines by default
static cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
D
duke 已提交
63

64 65
// This is the default factory
static cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
D
duke 已提交
66

67 68 69

// Main plug-in entry
cmsBool  _cmsRegisterInterpPlugin(cmsPluginBase* Data)
D
duke 已提交
70
{
71
    cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
D
duke 已提交
72

73
    if (Data == NULL) {
D
duke 已提交
74

75 76 77
        Interpolators = DefaultInterpolatorsFactory;
        return TRUE;
    }
D
duke 已提交
78

79 80 81 82
    // Set replacement functions
    Interpolators = Plugin ->InterpolatorsFactory;
    return TRUE;
}
D
duke 已提交
83 84


85
// Set the interpolation method
D
duke 已提交
86
static
87
cmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
D
duke 已提交
88
{
89 90
    // Invoke factory, possibly in the Plug-in
    p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
D
duke 已提交
91

92 93 94 95
    // 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 已提交
96

97 98 99 100 101 102
    // Check for valid interpolator (we just check one member of the union)
    if (p ->Interpolation.Lerp16 == NULL) {
            return FALSE;
    }
    return TRUE;
}
D
duke 已提交
103 104


105 106 107 108 109 110 111 112 113
// This function precalculates as many parameters as possible to speed up the interpolation.
cmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
                                           const cmsUInt32Number nSamples[],
                                           int InputChan, int OutputChan,
                                           const void *Table,
                                           cmsUInt32Number dwFlags)
{
    cmsInterpParams* p;
    int i;
D
duke 已提交
114

115 116 117 118 119
    // 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 已提交
120

121 122 123
    // Creates an empty object
    p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
    if (p == NULL) return NULL;
D
duke 已提交
124

125 126 127 128 129 130
    // Keep original parameters
    p -> dwFlags  = dwFlags;
    p -> nInputs  = InputChan;
    p -> nOutputs = OutputChan;
    p ->Table     = Table;
    p ->ContextID  = ContextID;
D
duke 已提交
131

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

135 136 137
        p -> nSamples[i] = nSamples[i];
        p -> Domain[i]   = nSamples[i] - 1;
    }
D
duke 已提交
138

139 140 141 142
    // 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 已提交
143 144


145 146 147 148 149
    if (!_cmsSetInterpolationRoutine(p)) {
         cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
        _cmsFree(ContextID, p);
        return NULL;
    }
D
duke 已提交
150

151 152 153
    // All seems ok
    return p;
}
D
duke 已提交
154 155


156 157 158 159 160
// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
cmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
{
    int i;
    cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
D
duke 已提交
161

162 163 164
    // Fill the auxiliar array
    for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
        Samples[i] = nSamples;
D
duke 已提交
165

166 167 168
    // Call the extended function
    return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
}
D
duke 已提交
169 170


171 172 173 174 175
// Free all associated memory
void _cmsFreeInterpParams(cmsInterpParams* p)
{
    if (p != NULL) _cmsFree(p ->ContextID, p);
}
D
duke 已提交
176 177


178 179 180 181 182 183
// 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 已提交
184 185 186
}


187
//  Linear interpolation (Fixed-point optimized)
D
duke 已提交
188
static
189 190 191
void LinLerp1D(register const cmsUInt16Number Value[],
               register cmsUInt16Number Output[],
               register const cmsInterpParams* p)
D
duke 已提交
192
{
193 194 195 196
    cmsUInt16Number y1, y0;
    int cell0, rest;
    int val3;
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
D
duke 已提交
197

198 199
    // if last value...
    if (Value[0] == 0xffff) {
D
duke 已提交
200

201 202 203
        Output[0] = LutTable[p -> Domain[0]];
        return;
    }
D
duke 已提交
204

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

208 209
    cell0 = FIXED_TO_INT(val3);             // Cell is 16 MSB bits
    rest  = FIXED_REST_TO_INT(val3);        // Rest is 16 LSB bits
D
duke 已提交
210

211 212
    y0 = LutTable[cell0];
    y1 = LutTable[cell0+1];
D
duke 已提交
213 214


215 216
    Output[0] = LinearInterp(rest, y0, y1);
}
D
duke 已提交
217 218


219 220 221 222 223 224 225 226 227 228
// 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 已提交
229

230 231 232 233
       // if last value...
       if (Value[0] == 1.0) {
           Output[0] = LutTable[p -> Domain[0]];
           return;
D
duke 已提交
234 235
       }

236 237 238 239 240 241 242 243 244 245 246 247
       val2 = p -> Domain[0] * Value[0];

       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 已提交
248 249 250
}


251 252

// Eval gray LUT having only one input channel
D
duke 已提交
253
static
254 255 256
void Eval1Input(register const cmsUInt16Number Input[],
                register cmsUInt16Number Output[],
                register const cmsInterpParams* p16)
D
duke 已提交
257
{
258 259 260 261 262
       cmsS15Fixed16Number fk;
       cmsS15Fixed16Number k0, k1, rk, K0, K1;
       int v;
       cmsUInt32Number OutChan;
       const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
D
duke 已提交
263

264 265
       v = Input[0] * p16 -> Domain[0];
       fk = _cmsToFixedDomain(v);
D
duke 已提交
266 267

       k0 = FIXED_TO_INT(fk);
268
       rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
D
duke 已提交
269

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

272 273
       K0 = p16 -> opta[0] * k0;
       K1 = p16 -> opta[0] * k1;
D
duke 已提交
274

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

277 278 279
           Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
       }
}
D
duke 已提交
280 281 282



283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
// 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;

        // if last value...
       if (Value[0] == 1.0) {
           Output[0] = LutTable[p -> Domain[0]];
           return;
D
duke 已提交
299 300
       }

301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
       val2 = p -> Domain[0] * Value[0];

       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 已提交
319 320
}

321 322 323


// Trilinear interpolation (16 bits) - cmsFloat32Number version
D
duke 已提交
324
static
325 326 327 328
void TrilinearInterpFloat(const cmsFloat32Number Input[],
                          cmsFloat32Number Output[],
                          const cmsInterpParams* p)

D
duke 已提交
329
{
330 331
#   define LERP(a,l,h)      (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
#   define DENS(i,j,k)      (LutTable[(i)+(j)+(k)+OutChan])
D
duke 已提交
332

333 334 335 336 337 338 339 340 341 342
    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 已提交
343

344
    TotalOut   = p -> nOutputs;
D
duke 已提交
345

346 347 348
    px = Input[0] * p->Domain[0];
    py = Input[1] * p->Domain[1];
    pz = Input[2] * p->Domain[2];
D
duke 已提交
349

350 351 352
    x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
    y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
    z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
D
duke 已提交
353

354 355
    X0 = p -> opta[2] * x0;
    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
D
duke 已提交
356

357 358
    Y0 = p -> opta[1] * y0;
    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
D
duke 已提交
359

360 361
    Z0 = p -> opta[0] * z0;
    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
D
duke 已提交
362

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

365 366 367 368
        d000 = DENS(X0, Y0, Z0);
        d001 = DENS(X0, Y0, Z1);
        d010 = DENS(X0, Y1, Z0);
        d011 = DENS(X0, Y1, Z1);
D
duke 已提交
369

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
        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 已提交
392 393
}

394
// Trilinear interpolation (16 bits) - optimized version
D
duke 已提交
395
static
396 397 398
void TrilinearInterp16(register const cmsUInt16Number Input[],
                       register cmsUInt16Number Output[],
                       register const cmsInterpParams* p)
D
duke 已提交
399

400 401 402
{
#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 已提交
403

404 405 406 407 408 409 410 411 412 413
           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 已提交
414

415
    TotalOut   = p -> nOutputs;
D
duke 已提交
416

417 418 419
    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 已提交
420 421


422 423 424
    fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
    y0  = FIXED_TO_INT(fy);
    ry  = FIXED_REST_TO_INT(fy);
D
duke 已提交
425

426 427 428
    fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
    z0 = FIXED_TO_INT(fz);
    rz = FIXED_REST_TO_INT(fz);
D
duke 已提交
429 430


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

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

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

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

442 443 444 445
        d000 = DENS(X0, Y0, Z0);
        d001 = DENS(X0, Y0, Z1);
        d010 = DENS(X0, Y1, Z0);
        d011 = DENS(X0, Y1, Z1);
D
duke 已提交
446

447 448 449 450
        d100 = DENS(X1, Y0, Z0);
        d101 = DENS(X1, Y0, Z1);
        d110 = DENS(X1, Y1, Z0);
        d111 = DENS(X1, Y1, Z1);
D
duke 已提交
451 452


453 454 455 456
        dx00 = LERP(rx, d000, d100);
        dx01 = LERP(rx, d001, d101);
        dx10 = LERP(rx, d010, d110);
        dx11 = LERP(rx, d011, d111);
D
duke 已提交
457

458 459
        dxy0 = LERP(ry, dx00, dx10);
        dxy1 = LERP(ry, dx01, dx11);
D
duke 已提交
460

461
        dxyz = LERP(rz, dxy0, dxy1);
D
duke 已提交
462

463 464
        Output[OutChan] = (cmsUInt16Number) dxyz;
    }
D
duke 已提交
465 466


467 468 469
#   undef LERP
#   undef DENS
}
D
duke 已提交
470 471


472 473 474 475 476 477 478 479 480 481 482 483 484 485
// 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 已提交
486

487
    TotalOut   = p -> nOutputs;
D
duke 已提交
488

489 490 491
    px = Input[0] * p->Domain[0];
    py = Input[1] * p->Domain[1];
    pz = Input[2] * p->Domain[2];
D
duke 已提交
492

493 494 495
    x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
    y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
    z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
D
duke 已提交
496 497


498 499
    X0 = p -> opta[2] * x0;
    X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
D
duke 已提交
500

501 502
    Y0 = p -> opta[1] * y0;
    Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
D
duke 已提交
503

504 505
    Z0 = p -> opta[0] * z0;
    Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
D
duke 已提交
506

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

509
       // These are the 6 Tetrahedral
D
duke 已提交
510

511
        c0 = DENS(X0, Y0, Z0);
D
duke 已提交
512

513
        if (rx >= ry && ry >= rz) {
D
duke 已提交
514

515 516 517
            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 已提交
518

519 520 521
        }
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
522

523 524 525
                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 已提交
526

527 528 529
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
530

531 532 533
                    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 已提交
534

535 536 537
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
538

539 540 541
                        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 已提交
542

543 544 545
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
546

547 548 549
                            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 已提交
550

551 552 553
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
554

555 556 557
                                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 已提交
558

559 560 561 562
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
563

564 565
       Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
       }
D
duke 已提交
566 567 568

}

569
#undef DENS
D
duke 已提交
570 571 572



573
#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
D
duke 已提交
574

575 576 577 578
static
void TetrahedralInterp16(register const cmsUInt16Number Input[],
                         register cmsUInt16Number Output[],
                         register const cmsInterpParams* p)
D
duke 已提交
579
{
580 581 582 583 584 585 586 587
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
    cmsS15Fixed16Number    fx, fy, fz;
    cmsS15Fixed16Number    rx, ry, rz;
    int                    x0, y0, z0;
    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
    cmsUInt32Number        OutChan;
    cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
    cmsUInt32Number        TotalOut = p -> nOutputs;
D
duke 已提交
588 589


590 591 592
    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 已提交
593

594 595 596
    x0  = FIXED_TO_INT(fx);
    y0  = FIXED_TO_INT(fy);
    z0  = FIXED_TO_INT(fz);
D
duke 已提交
597

598 599 600
    rx  = FIXED_REST_TO_INT(fx);
    ry  = FIXED_REST_TO_INT(fy);
    rz  = FIXED_REST_TO_INT(fz);
D
duke 已提交
601

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

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

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

611 612
    // These are the 6 Tetrahedral
    for (OutChan=0; OutChan < TotalOut; OutChan++) {
D
duke 已提交
613

614
        c0 = DENS(X0, Y0, Z0);
D
duke 已提交
615

616
        if (rx >= ry && ry >= rz) {
D
duke 已提交
617

618 619 620
            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 已提交
621

622 623 624
        }
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
625

626 627 628
                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 已提交
629

630 631 632
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
633

634 635 636
                    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 已提交
637

638 639 640
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
641

642 643 644
                        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 已提交
645

646 647 648
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
649

650 651 652
                            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 已提交
653

654 655 656
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
657

658 659 660
                                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 已提交
661

662 663 664 665
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
666

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

669 670
                            Output[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
    }
D
duke 已提交
671 672

}
673
#undef DENS
D
duke 已提交
674 675


676 677 678 679 680
#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 已提交
681
{
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
    const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
    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 已提交
705

706 707 708 709
    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 已提交
710

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

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

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

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

723 724
    LutTable = (cmsUInt16Number*) p16 -> Table;
    LutTable += K0;
D
duke 已提交
725

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

728 729 730 731 732 733 734
        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 已提交
735 736

        }
737 738
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
739

740 741 742
                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 已提交
743

744 745 746
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
747

748 749 750
                    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 已提交
751

752 753 754
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
755

756 757 758
                        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 已提交
759

760 761 762
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
763

764 765 766
                            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 已提交
767

768 769 770
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
771

772 773 774
                                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 已提交
775

776 777 778 779
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
780

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

783 784
                            Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
    }
D
duke 已提交
785 786


787 788
    LutTable = (cmsUInt16Number*) p16 -> Table;
    LutTable += K1;
D
duke 已提交
789

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

792
        c0 = DENS(X0, Y0, Z0);
D
duke 已提交
793

794
        if (rx >= ry && ry >= rz) {
D
duke 已提交
795

796 797 798
            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 已提交
799

800 801 802
        }
        else
            if (rx >= rz && rz >= ry) {
D
duke 已提交
803

804 805 806
                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 已提交
807

808 809 810
            }
            else
                if (rz >= rx && rx >= ry) {
D
duke 已提交
811

812 813 814
                    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 已提交
815

816 817 818
                }
                else
                    if (ry >= rx && rx >= rz) {
D
duke 已提交
819

820 821 822
                        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 已提交
823

824 825 826
                    }
                    else
                        if (ry >= rz && rz >= rx) {
D
duke 已提交
827

828 829 830
                            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 已提交
831

832 833 834
                        }
                        else
                            if (rz >= ry && ry >= rx) {
D
duke 已提交
835

836 837 838
                                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 已提交
839

840 841 842 843
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }
D
duke 已提交
844

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

847 848
                            Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
    }
D
duke 已提交
849 850 851



852 853 854 855 856
    for (i=0; i < p16 -> nOutputs; i++) {
        Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
    }
}
#undef DENS
D
duke 已提交
857 858


859 860
// For more that 3 inputs (i.e., CMYK)
// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
D
duke 已提交
861 862


863 864 865 866 867 868 869 870 871 872 873 874 875
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 已提交
876 877


878 879 880
       pk = Input[0] * p->Domain[0];
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
881

882 883
       K0 = p -> opta[3] * k0;
       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
D
duke 已提交
884

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

888 889
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
890

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

893 894 895
       T = LutTable + K1;
       p1.Table = T;
       TetrahedralInterpFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
896

897 898 899 900
       for (i=0; i < p -> nOutputs; i++)
       {
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];
D
duke 已提交
901

902 903 904
              Output[i] = y0 + (y1 - y0) * rest;
       }
}
D
duke 已提交
905 906


907 908 909
static
void Eval5Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
D
duke 已提交
910

911 912 913 914 915 916 917 918 919 920
                 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 已提交
921 922


923 924 925
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
926

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

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

933 934
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
935

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

938 939
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
940

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

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

945 946
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
D
duke 已提交
947

948
}
D
duke 已提交
949 950


951 952 953 954 955 956 957 958 959 960 961 962 963
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 已提交
964

965 966 967
       pk = Input[0] * p->Domain[0];
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
968

969 970
       K0 = p -> opta[4] * k0;
       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
D
duke 已提交
971

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

975 976
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
977

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

980 981
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
982

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

985 986 987 988 989 990 991
       for (i=0; i < p -> nOutputs; i++) {

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

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



996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
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 已提交
1009

1010 1011 1012
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1013

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

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

1020 1021
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1022

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

1025 1026
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1027

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

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

1032 1033
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
D
duke 已提交
1034

1035
}
D
duke 已提交
1036 1037


1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
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 已提交
1051

1052 1053 1054
       pk = Input[0] * p->Domain[0];
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1055

1056 1057
       K0 = p -> opta[5] * k0;
       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
D
duke 已提交
1058

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

1062 1063
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1064

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

1067 1068
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1069

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

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

1074 1075
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];
D
duke 已提交
1076

1077 1078 1079
              Output[i] = y0 + (y1 - y0) * rest;
       }
}
D
duke 已提交
1080 1081


1082 1083 1084 1085
static
void Eval7Inputs(register const cmsUInt16Number Input[],
                 register cmsUInt16Number Output[],
                 register const cmsInterpParams* p16)
D
duke 已提交
1086
{
1087 1088 1089 1090 1091 1092 1093 1094
       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 已提交
1095 1096


1097 1098 1099
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1100

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

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

1107 1108
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1109

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

1112 1113
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1114

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

1117 1118 1119 1120
       for (i=0; i < p16 -> nOutputs; i++) {
              Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
       }
}
D
duke 已提交
1121 1122


1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
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 已提交
1136

1137 1138 1139
       pk = Input[0] * p->Domain[0];
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1140

1141 1142
       K0 = p -> opta[6] * k0;
       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
D
duke 已提交
1143

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

1147 1148
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1149

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

1152 1153
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1154

1155
       Eval6InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1156 1157


1158 1159 1160 1161
       for (i=0; i < p -> nOutputs; i++) {

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

1163
              Output[i] = y0 + (y1 - y0) * rest;
D
duke 已提交
1164 1165

       }
1166
}
D
duke 已提交
1167

1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
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 已提交
1181

1182 1183 1184
       fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
       k0 = FIXED_TO_INT(fk);
       rk = FIXED_REST_TO_INT(fk);
D
duke 已提交
1185

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

1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
       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 已提交
1203
       }
1204
}
D
duke 已提交
1205 1206 1207



1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220
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 已提交
1221

1222 1223 1224
       pk = Input[0] * p->Domain[0];
       k0 = _cmsQuickFloor(pk);
       rest = pk - (cmsFloat32Number) k0;
D
duke 已提交
1225

1226 1227 1228 1229 1230
       K0 = p -> opta[7] * k0;
       K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);

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

1232 1233
       T = LutTable + K0;
       p1.Table = T;
D
duke 已提交
1234

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

1237 1238
       T = LutTable + K1;
       p1.Table = T;
D
duke 已提交
1239

1240
       Eval7InputsFloat(Input + 1,  Tmp2, &p1);
D
duke 已提交
1241 1242


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

1245 1246 1247 1248 1249 1250
              cmsFloat32Number y0 = Tmp1[i];
              cmsFloat32Number y1 = Tmp2[i];

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

1252 1253 1254
// The default factory
static
cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
D
duke 已提交
1255 1256
{

1257 1258 1259
    cmsInterpFunction Interpolation;
    cmsBool  IsFloat     = (dwFlags & CMS_LERP_FLAGS_FLOAT);
    cmsBool  IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
D
duke 已提交
1260

1261
    memset(&Interpolation, 0, sizeof(Interpolation));
D
duke 已提交
1262

1263 1264 1265
    // Safety check
    if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
        return Interpolation;
D
duke 已提交
1266

1267
    switch (nInputChannels) {
D
duke 已提交
1268

1269
           case 1: // Gray LUT / linear
D
duke 已提交
1270

1271
               if (nOutputChannels == 1) {
D
duke 已提交
1272

1273 1274 1275 1276
                   if (IsFloat)
                       Interpolation.LerpFloat = LinLerp1Dfloat;
                   else
                       Interpolation.Lerp16 = LinLerp1D;
D
duke 已提交
1277

1278 1279
               }
               else {
D
duke 已提交
1280

1281 1282 1283 1284 1285 1286
                   if (IsFloat)
                       Interpolation.LerpFloat = Eval1InputFloat;
                   else
                       Interpolation.Lerp16 = Eval1Input;
               }
               break;
D
duke 已提交
1287 1288


1289
           case 3:  // RGB et al
D
duke 已提交
1290

1291
               if (IsTrilinear) {
D
duke 已提交
1292

1293 1294 1295 1296 1297 1298
                   if (IsFloat)
                       Interpolation.LerpFloat = TrilinearInterpFloat;
                   else
                       Interpolation.Lerp16 = TrilinearInterp16;
               }
               else {
D
duke 已提交
1299

1300 1301 1302
                   if (IsFloat)
                       Interpolation.LerpFloat = TetrahedralInterpFloat;
                   else {
D
duke 已提交
1303

1304 1305 1306 1307
                       Interpolation.Lerp16 = TetrahedralInterp16;
                   }
               }
               break;
D
duke 已提交
1308

1309
           case 4:  // CMYK lut
D
duke 已提交
1310

1311 1312 1313 1314 1315
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval4InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval4Inputs;
               break;
D
duke 已提交
1316

1317 1318 1319 1320 1321 1322
           case 5: // 5 Inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval5InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval5Inputs;
               break;
D
duke 已提交
1323

1324 1325 1326 1327 1328 1329
           case 6: // 6 Inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval6InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval6Inputs;
               break;
D
duke 已提交
1330

1331 1332 1333 1334 1335 1336
           case 7: // 7 inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval7InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval7Inputs;
               break;
D
duke 已提交
1337

1338 1339 1340 1341 1342 1343
           case 8: // 8 inks
               if (IsFloat)
                   Interpolation.LerpFloat =  Eval8InputsFloat;
               else
                   Interpolation.Lerp16    =  Eval8Inputs;
               break;
D
duke 已提交
1344

1345
               break;
D
duke 已提交
1346

1347 1348
           default:
               Interpolation.Lerp16 = NULL;
D
duke 已提交
1349 1350
    }

1351
    return Interpolation;
D
duke 已提交
1352
}