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