0N/A/*
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A// This file is available under and governed by the GNU General Public
0N/A// License version 2 only, as published by the Free Software Foundation.
0N/A// However, the following notice accompanied the original version of this
0N/A// file:
0N/A//
2693N/A//---------------------------------------------------------------------------------
0N/A//
2693N/A// Little Color Management System
6271N/A// Copyright (c) 1998-2012 Marti Maria Saguer
0N/A//
0N/A// Permission is hereby granted, free of charge, to any person obtaining
0N/A// a copy of this software and associated documentation files (the "Software"),
0N/A// to deal in the Software without restriction, including without limitation
0N/A// the rights to use, copy, modify, merge, publish, distribute, sublicense,
0N/A// and/or sell copies of the Software, and to permit persons to whom the Software
0N/A// is furnished to do so, subject to the following conditions:
0N/A//
0N/A// The above copyright notice and this permission notice shall be included in
0N/A// all copies or substantial portions of the Software.
0N/A//
0N/A// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0N/A// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
0N/A// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0N/A// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
0N/A// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0N/A// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0N/A// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2693N/A//
2693N/A//---------------------------------------------------------------------------------
2693N/A//
0N/A
2693N/A#include "lcms2_internal.h"
0N/A
6271N/A// This module incorporates several interpolation routines, for 1 to 8 channels on input and
2693N/A// up to 65535 channels on output. The user may change those by using the interpolation plug-in
0N/A
2693N/A// Interpolation routines by default
2693N/Astatic cmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags);
0N/A
2693N/A// This is the default factory
2693N/Astatic cmsInterpFnFactory Interpolators = DefaultInterpolatorsFactory;
0N/A
0N/A
2693N/A// Main plug-in entry
2693N/AcmsBool _cmsRegisterInterpPlugin(cmsPluginBase* Data)
2693N/A{
2693N/A cmsPluginInterpolation* Plugin = (cmsPluginInterpolation*) Data;
0N/A
2693N/A if (Data == NULL) {
0N/A
2693N/A Interpolators = DefaultInterpolatorsFactory;
2693N/A return TRUE;
2693N/A }
0N/A
2693N/A // Set replacement functions
2693N/A Interpolators = Plugin ->InterpolatorsFactory;
2693N/A return TRUE;
0N/A}
0N/A
0N/A
2693N/A// Set the interpolation method
6271N/A
2693N/AcmsBool _cmsSetInterpolationRoutine(cmsInterpParams* p)
0N/A{
2693N/A // Invoke factory, possibly in the Plug-in
2693N/A p ->Interpolation = Interpolators(p -> nInputs, p ->nOutputs, p ->dwFlags);
0N/A
2693N/A // If unsupported by the plug-in, go for the LittleCMS default.
2693N/A // If happens only if an extern plug-in is being used
2693N/A if (p ->Interpolation.Lerp16 == NULL)
2693N/A p ->Interpolation = DefaultInterpolatorsFactory(p ->nInputs, p ->nOutputs, p ->dwFlags);
0N/A
2693N/A // Check for valid interpolator (we just check one member of the union)
2693N/A if (p ->Interpolation.Lerp16 == NULL) {
2693N/A return FALSE;
2693N/A }
2693N/A return TRUE;
0N/A}
0N/A
0N/A
2693N/A// This function precalculates as many parameters as possible to speed up the interpolation.
2693N/AcmsInterpParams* _cmsComputeInterpParamsEx(cmsContext ContextID,
2693N/A const cmsUInt32Number nSamples[],
2693N/A int InputChan, int OutputChan,
2693N/A const void *Table,
2693N/A cmsUInt32Number dwFlags)
0N/A{
2693N/A cmsInterpParams* p;
2693N/A int i;
0N/A
2693N/A // Check for maximum inputs
2693N/A if (InputChan > MAX_INPUT_DIMENSIONS) {
2693N/A cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", InputChan, MAX_INPUT_DIMENSIONS);
2693N/A return NULL;
2693N/A }
0N/A
2693N/A // Creates an empty object
2693N/A p = (cmsInterpParams*) _cmsMallocZero(ContextID, sizeof(cmsInterpParams));
2693N/A if (p == NULL) return NULL;
0N/A
2693N/A // Keep original parameters
2693N/A p -> dwFlags = dwFlags;
2693N/A p -> nInputs = InputChan;
2693N/A p -> nOutputs = OutputChan;
2693N/A p ->Table = Table;
2693N/A p ->ContextID = ContextID;
0N/A
2693N/A // Fill samples per input direction and domain (which is number of nodes minus one)
2693N/A for (i=0; i < InputChan; i++) {
0N/A
2693N/A p -> nSamples[i] = nSamples[i];
2693N/A p -> Domain[i] = nSamples[i] - 1;
2693N/A }
2693N/A
2693N/A // Compute factors to apply to each component to index the grid array
2693N/A p -> opta[0] = p -> nOutputs;
2693N/A for (i=1; i < InputChan; i++)
2693N/A p ->opta[i] = p ->opta[i-1] * nSamples[InputChan-i];
0N/A
0N/A
2693N/A if (!_cmsSetInterpolationRoutine(p)) {
2693N/A cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported interpolation (%d->%d channels)", InputChan, OutputChan);
2693N/A _cmsFree(ContextID, p);
2693N/A return NULL;
2693N/A }
0N/A
2693N/A // All seems ok
2693N/A return p;
0N/A}
0N/A
2693N/A
2693N/A// This one is a wrapper on the anterior, but assuming all directions have same number of nodes
2693N/AcmsInterpParams* _cmsComputeInterpParams(cmsContext ContextID, int nSamples, int InputChan, int OutputChan, const void* Table, cmsUInt32Number dwFlags)
0N/A{
2693N/A int i;
2693N/A cmsUInt32Number Samples[MAX_INPUT_DIMENSIONS];
0N/A
2693N/A // Fill the auxiliar array
2693N/A for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
2693N/A Samples[i] = nSamples;
0N/A
2693N/A // Call the extended function
2693N/A return _cmsComputeInterpParamsEx(ContextID, Samples, InputChan, OutputChan, Table, dwFlags);
0N/A}
0N/A
0N/A
2693N/A// Free all associated memory
2693N/Avoid _cmsFreeInterpParams(cmsInterpParams* p)
0N/A{
2693N/A if (p != NULL) _cmsFree(p ->ContextID, p);
2693N/A}
0N/A
0N/A
2693N/A// Inline fixed point interpolation
2693N/AcmsINLINE cmsUInt16Number LinearInterp(cmsS15Fixed16Number a, cmsS15Fixed16Number l, cmsS15Fixed16Number h)
2693N/A{
2693N/A cmsUInt32Number dif = (cmsUInt32Number) (h - l) * a + 0x8000;
2693N/A dif = (dif >> 16) + l;
2693N/A return (cmsUInt16Number) (dif);
0N/A}
0N/A
0N/A
2693N/A// Linear interpolation (Fixed-point optimized)
2693N/Astatic
2693N/Avoid LinLerp1D(register const cmsUInt16Number Value[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p)
0N/A{
2693N/A cmsUInt16Number y1, y0;
2693N/A int cell0, rest;
2693N/A int val3;
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
2693N/A
2693N/A // if last value...
2693N/A if (Value[0] == 0xffff) {
2693N/A
2693N/A Output[0] = LutTable[p -> Domain[0]];
2693N/A return;
2693N/A }
2693N/A
2693N/A val3 = p -> Domain[0] * Value[0];
2693N/A val3 = _cmsToFixedDomain(val3); // To fixed 15.16
2693N/A
2693N/A cell0 = FIXED_TO_INT(val3); // Cell is 16 MSB bits
2693N/A rest = FIXED_REST_TO_INT(val3); // Rest is 16 LSB bits
2693N/A
2693N/A y0 = LutTable[cell0];
2693N/A y1 = LutTable[cell0+1];
2693N/A
2693N/A
2693N/A Output[0] = LinearInterp(rest, y0, y1);
0N/A}
0N/A
0N/A
2693N/A// Floating-point version of 1D interpolation
2693N/Astatic
2693N/Avoid LinLerp1Dfloat(const cmsFloat32Number Value[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
0N/A{
2693N/A cmsFloat32Number y1, y0;
2693N/A cmsFloat32Number val2, rest;
0N/A int cell0, cell1;
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
0N/A
0N/A // if last value...
2693N/A if (Value[0] == 1.0) {
2693N/A Output[0] = LutTable[p -> Domain[0]];
2693N/A return;
2693N/A }
0N/A
2693N/A val2 = p -> Domain[0] * Value[0];
0N/A
0N/A cell0 = (int) floor(val2);
0N/A cell1 = (int) ceil(val2);
0N/A
0N/A // Rest is 16 LSB bits
0N/A rest = val2 - cell0;
0N/A
0N/A y0 = LutTable[cell0] ;
0N/A y1 = LutTable[cell1] ;
0N/A
2693N/A Output[0] = y0 + (y1 - y0) * rest;
0N/A}
0N/A
0N/A
0N/A
2693N/A// Eval gray LUT having only one input channel
2693N/Astatic
2693N/Avoid Eval1Input(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p16)
0N/A{
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, k1, rk, K0, K1;
2693N/A int v;
2693N/A cmsUInt32Number OutChan;
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
0N/A
2693N/A v = Input[0] * p16 -> Domain[0];
2693N/A fk = _cmsToFixedDomain(v);
0N/A
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A rk = (cmsUInt16Number) FIXED_REST_TO_INT(fk);
0N/A
2693N/A k1 = k0 + (Input[0] != 0xFFFFU ? 1 : 0);
0N/A
2693N/A K0 = p16 -> opta[0] * k0;
2693N/A K1 = p16 -> opta[0] * k1;
0N/A
2693N/A for (OutChan=0; OutChan < p16->nOutputs; OutChan++) {
0N/A
2693N/A Output[OutChan] = LinearInterp(rk, LutTable[K0+OutChan], LutTable[K1+OutChan]);
2693N/A }
0N/A}
0N/A
0N/A
0N/A
2693N/A// Eval gray LUT having only one input channel
2693N/Astatic
2693N/Avoid Eval1InputFloat(const cmsFloat32Number Value[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A{
2693N/A cmsFloat32Number y1, y0;
2693N/A cmsFloat32Number val2, rest;
2693N/A int cell0, cell1;
2693N/A cmsUInt32Number OutChan;
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
0N/A
2693N/A // if last value...
2693N/A if (Value[0] == 1.0) {
2693N/A Output[0] = LutTable[p -> Domain[0]];
2693N/A return;
2693N/A }
0N/A
2693N/A val2 = p -> Domain[0] * Value[0];
2693N/A
2693N/A cell0 = (int) floor(val2);
2693N/A cell1 = (int) ceil(val2);
2693N/A
2693N/A // Rest is 16 LSB bits
2693N/A rest = val2 - cell0;
0N/A
2693N/A cell0 *= p -> opta[0];
2693N/A cell1 *= p -> opta[0];
2693N/A
2693N/A for (OutChan=0; OutChan < p->nOutputs; OutChan++) {
2693N/A
2693N/A y0 = LutTable[cell0 + OutChan] ;
2693N/A y1 = LutTable[cell1 + OutChan] ;
2693N/A
2693N/A Output[OutChan] = y0 + (y1 - y0) * rest;
2693N/A }
2693N/A}
0N/A
6271N/A// Bilinear interpolation (16 bits) - cmsFloat32Number version
6271N/Astatic
6271N/Avoid BilinearInterpFloat(const cmsFloat32Number Input[],
6271N/A cmsFloat32Number Output[],
6271N/A const cmsInterpParams* p)
6271N/A
6271N/A{
6271N/A# define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
6271N/A# define DENS(i,j) (LutTable[(i)+(j)+OutChan])
6271N/A
6271N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
6271N/A cmsFloat32Number px, py;
6271N/A int x0, y0,
6271N/A X0, Y0, X1, Y1;
6271N/A int TotalOut, OutChan;
6271N/A cmsFloat32Number fx, fy,
6271N/A d00, d01, d10, d11,
6271N/A dx0, dx1,
6271N/A dxy;
6271N/A
6271N/A TotalOut = p -> nOutputs;
6271N/A px = Input[0] * p->Domain[0];
6271N/A py = Input[1] * p->Domain[1];
6271N/A
6271N/A x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
6271N/A y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
6271N/A
6271N/A X0 = p -> opta[1] * x0;
6271N/A X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[1]);
6271N/A
6271N/A Y0 = p -> opta[0] * y0;
6271N/A Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[0]);
6271N/A
6271N/A for (OutChan = 0; OutChan < TotalOut; OutChan++) {
6271N/A
6271N/A d00 = DENS(X0, Y0);
6271N/A d01 = DENS(X0, Y1);
6271N/A d10 = DENS(X1, Y0);
6271N/A d11 = DENS(X1, Y1);
6271N/A
6271N/A dx0 = LERP(fx, d00, d10);
6271N/A dx1 = LERP(fx, d01, d11);
6271N/A
6271N/A dxy = LERP(fy, dx0, dx1);
6271N/A
6271N/A Output[OutChan] = dxy;
6271N/A }
6271N/A
6271N/A
6271N/A# undef LERP
6271N/A# undef DENS
6271N/A}
6271N/A
6271N/A// Bilinear interpolation (16 bits) - optimized version
6271N/Astatic
6271N/Avoid BilinearInterp16(register const cmsUInt16Number Input[],
6271N/A register cmsUInt16Number Output[],
6271N/A register const cmsInterpParams* p)
6271N/A
6271N/A{
6271N/A#define DENS(i,j) (LutTable[(i)+(j)+OutChan])
6271N/A#define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
6271N/A
6271N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
6271N/A int OutChan, TotalOut;
6271N/A cmsS15Fixed16Number fx, fy;
6271N/A register int rx, ry;
6271N/A int x0, y0;
6271N/A register int X0, X1, Y0, Y1;
6271N/A int d00, d01, d10, d11,
6271N/A dx0, dx1,
6271N/A dxy;
6271N/A
6271N/A TotalOut = p -> nOutputs;
6271N/A
6271N/A fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
6271N/A x0 = FIXED_TO_INT(fx);
6271N/A rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
6271N/A
6271N/A
6271N/A fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
6271N/A y0 = FIXED_TO_INT(fy);
6271N/A ry = FIXED_REST_TO_INT(fy);
6271N/A
6271N/A
6271N/A X0 = p -> opta[1] * x0;
6271N/A X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[1]);
6271N/A
6271N/A Y0 = p -> opta[0] * y0;
6271N/A Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[0]);
6271N/A
6271N/A for (OutChan = 0; OutChan < TotalOut; OutChan++) {
6271N/A
6271N/A d00 = DENS(X0, Y0);
6271N/A d01 = DENS(X0, Y1);
6271N/A d10 = DENS(X1, Y0);
6271N/A d11 = DENS(X1, Y1);
6271N/A
6271N/A dx0 = LERP(rx, d00, d10);
6271N/A dx1 = LERP(rx, d01, d11);
6271N/A
6271N/A dxy = LERP(ry, dx0, dx1);
6271N/A
6271N/A Output[OutChan] = (cmsUInt16Number) dxy;
6271N/A }
6271N/A
6271N/A
6271N/A# undef LERP
6271N/A# undef DENS
6271N/A}
0N/A
0N/A
2693N/A// Trilinear interpolation (16 bits) - cmsFloat32Number version
2693N/Astatic
2693N/Avoid TrilinearInterpFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A
2693N/A{
2693N/A# define LERP(a,l,h) (cmsFloat32Number) ((l)+(((h)-(l))*(a)))
2693N/A# define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
2693N/A
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
2693N/A cmsFloat32Number px, py, pz;
0N/A int x0, y0, z0,
2693N/A X0, Y0, Z0, X1, Y1, Z1;
2693N/A int TotalOut, OutChan;
2693N/A cmsFloat32Number fx, fy, fz,
2693N/A d000, d001, d010, d011,
2693N/A d100, d101, d110, d111,
2693N/A dx00, dx01, dx10, dx11,
2693N/A dxy0, dxy1, dxyz;
0N/A
0N/A TotalOut = p -> nOutputs;
0N/A
6271N/A // We need some clipping here
6271N/A px = Input[0];
6271N/A py = Input[1];
6271N/A pz = Input[2];
6271N/A
6271N/A if (px < 0) px = 0;
6271N/A if (px > 1) px = 1;
6271N/A if (py < 0) py = 0;
6271N/A if (py > 1) py = 1;
6271N/A if (pz < 0) pz = 0;
6271N/A if (pz > 1) pz = 1;
6271N/A
6271N/A px *= p->Domain[0];
6271N/A py *= p->Domain[1];
6271N/A pz *= p->Domain[2];
2693N/A
2693N/A x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
2693N/A y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
2693N/A z0 = (int) _cmsQuickFloor(pz); fz = pz - (cmsFloat32Number) z0;
2693N/A
2693N/A X0 = p -> opta[2] * x0;
2693N/A X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
2693N/A
2693N/A Y0 = p -> opta[1] * y0;
2693N/A Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
0N/A
2693N/A Z0 = p -> opta[0] * z0;
2693N/A Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
2693N/A
2693N/A for (OutChan = 0; OutChan < TotalOut; OutChan++) {
0N/A
2693N/A d000 = DENS(X0, Y0, Z0);
2693N/A d001 = DENS(X0, Y0, Z1);
2693N/A d010 = DENS(X0, Y1, Z0);
2693N/A d011 = DENS(X0, Y1, Z1);
2693N/A
2693N/A d100 = DENS(X1, Y0, Z0);
2693N/A d101 = DENS(X1, Y0, Z1);
2693N/A d110 = DENS(X1, Y1, Z0);
2693N/A d111 = DENS(X1, Y1, Z1);
0N/A
0N/A
2693N/A dx00 = LERP(fx, d000, d100);
2693N/A dx01 = LERP(fx, d001, d101);
2693N/A dx10 = LERP(fx, d010, d110);
2693N/A dx11 = LERP(fx, d011, d111);
0N/A
2693N/A dxy0 = LERP(fy, dx00, dx10);
2693N/A dxy1 = LERP(fy, dx01, dx11);
0N/A
2693N/A dxyz = LERP(fz, dxy0, dxy1);
0N/A
2693N/A Output[OutChan] = dxyz;
0N/A }
0N/A
0N/A
0N/A# undef LERP
0N/A# undef DENS
0N/A}
0N/A
0N/A// Trilinear interpolation (16 bits) - optimized version
2693N/Astatic
2693N/Avoid TrilinearInterp16(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p)
0N/A
0N/A{
0N/A#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
2693N/A#define LERP(a,l,h) (cmsUInt16Number) (l + ROUND_FIXED_TO_INT(((h-l)*a)))
0N/A
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p ->Table;
0N/A int OutChan, TotalOut;
2693N/A cmsS15Fixed16Number fx, fy, fz;
0N/A register int rx, ry, rz;
0N/A int x0, y0, z0;
0N/A register int X0, X1, Y0, Y1, Z0, Z1;
0N/A int d000, d001, d010, d011,
0N/A d100, d101, d110, d111,
0N/A dx00, dx01, dx10, dx11,
0N/A dxy0, dxy1, dxyz;
0N/A
0N/A TotalOut = p -> nOutputs;
0N/A
2693N/A fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
0N/A x0 = FIXED_TO_INT(fx);
0N/A rx = FIXED_REST_TO_INT(fx); // Rest in 0..1.0 domain
0N/A
0N/A
2693N/A fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
0N/A y0 = FIXED_TO_INT(fy);
0N/A ry = FIXED_REST_TO_INT(fy);
0N/A
2693N/A fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
0N/A z0 = FIXED_TO_INT(fz);
0N/A rz = FIXED_REST_TO_INT(fz);
0N/A
0N/A
2693N/A X0 = p -> opta[2] * x0;
2693N/A X1 = X0 + (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
0N/A
2693N/A Y0 = p -> opta[1] * y0;
2693N/A Y1 = Y0 + (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
0N/A
2693N/A Z0 = p -> opta[0] * z0;
2693N/A Z1 = Z0 + (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
0N/A
2693N/A for (OutChan = 0; OutChan < TotalOut; OutChan++) {
0N/A
0N/A d000 = DENS(X0, Y0, Z0);
0N/A d001 = DENS(X0, Y0, Z1);
0N/A d010 = DENS(X0, Y1, Z0);
0N/A d011 = DENS(X0, Y1, Z1);
0N/A
0N/A d100 = DENS(X1, Y0, Z0);
0N/A d101 = DENS(X1, Y0, Z1);
0N/A d110 = DENS(X1, Y1, Z0);
0N/A d111 = DENS(X1, Y1, Z1);
0N/A
0N/A
0N/A dx00 = LERP(rx, d000, d100);
0N/A dx01 = LERP(rx, d001, d101);
0N/A dx10 = LERP(rx, d010, d110);
0N/A dx11 = LERP(rx, d011, d111);
0N/A
0N/A dxy0 = LERP(ry, dx00, dx10);
0N/A dxy1 = LERP(ry, dx01, dx11);
0N/A
0N/A dxyz = LERP(rz, dxy0, dxy1);
0N/A
2693N/A Output[OutChan] = (cmsUInt16Number) dxyz;
0N/A }
0N/A
0N/A
0N/A# undef LERP
0N/A# undef DENS
0N/A}
0N/A
0N/A
0N/A// Tetrahedral interpolation, using Sakamoto algorithm.
2693N/A#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
2693N/Astatic
2693N/Avoid TetrahedralInterpFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
0N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number px, py, pz;
0N/A int x0, y0, z0,
2693N/A X0, Y0, Z0, X1, Y1, Z1;
2693N/A cmsFloat32Number rx, ry, rz;
2693N/A cmsFloat32Number c0, c1=0, c2=0, c3=0;
2693N/A int OutChan, TotalOut;
0N/A
0N/A TotalOut = p -> nOutputs;
0N/A
6271N/A // We need some clipping here
6271N/A px = Input[0];
6271N/A py = Input[1];
6271N/A pz = Input[2];
6271N/A
6271N/A if (px < 0) px = 0;
6271N/A if (px > 1) px = 1;
6271N/A if (py < 0) py = 0;
6271N/A if (py > 1) py = 1;
6271N/A if (pz < 0) pz = 0;
6271N/A if (pz > 1) pz = 1;
6271N/A
6271N/A px *= p->Domain[0];
6271N/A py *= p->Domain[1];
6271N/A pz *= p->Domain[2];
0N/A
2693N/A x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
2693N/A y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
2693N/A z0 = (int) _cmsQuickFloor(pz); rz = (pz - (cmsFloat32Number) z0);
0N/A
0N/A
2693N/A X0 = p -> opta[2] * x0;
2693N/A X1 = X0 + (Input[0] >= 1.0 ? 0 : p->opta[2]);
0N/A
2693N/A Y0 = p -> opta[1] * y0;
2693N/A Y1 = Y0 + (Input[1] >= 1.0 ? 0 : p->opta[1]);
0N/A
2693N/A Z0 = p -> opta[0] * z0;
2693N/A Z1 = Z0 + (Input[2] >= 1.0 ? 0 : p->opta[0]);
2693N/A
2693N/A for (OutChan=0; OutChan < TotalOut; OutChan++) {
0N/A
0N/A // These are the 6 Tetrahedral
0N/A
2693N/A c0 = DENS(X0, Y0, Z0);
2693N/A
2693N/A if (rx >= ry && ry >= rz) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rx >= rz && rz >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rz >= rx && rx >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
0N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rx && rx >= rz) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rz && rz >= rx) {
0N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
0N/A
2693N/A }
2693N/A else
2693N/A if (rz >= ry && ry >= rx) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
2693N/A
2693N/A }
2693N/A else {
2693N/A c1 = c2 = c3 = 0;
2693N/A }
2693N/A
2693N/A Output[OutChan] = c0 + c1 * rx + c2 * ry + c3 * rz;
0N/A }
0N/A
0N/A}
0N/A
0N/A#undef DENS
0N/A
2693N/A
0N/A
0N/A
2693N/Astatic
2693N/Avoid TetrahedralInterp16(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p)
0N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p -> Table;
6271N/A cmsS15Fixed16Number fx, fy, fz;
6271N/A cmsS15Fixed16Number rx, ry, rz;
6271N/A int x0, y0, z0;
6271N/A cmsS15Fixed16Number c0, c1, c2, c3, Rest;
6271N/A cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
6271N/A cmsUInt32Number TotalOut = p -> nOutputs;
0N/A
6271N/A fx = _cmsToFixedDomain((int) Input[0] * p -> Domain[0]);
6271N/A fy = _cmsToFixedDomain((int) Input[1] * p -> Domain[1]);
6271N/A fz = _cmsToFixedDomain((int) Input[2] * p -> Domain[2]);
0N/A
6271N/A x0 = FIXED_TO_INT(fx);
6271N/A y0 = FIXED_TO_INT(fy);
6271N/A z0 = FIXED_TO_INT(fz);
0N/A
6271N/A rx = FIXED_REST_TO_INT(fx);
6271N/A ry = FIXED_REST_TO_INT(fy);
6271N/A rz = FIXED_REST_TO_INT(fz);
0N/A
2693N/A X0 = p -> opta[2] * x0;
6271N/A X1 = (Input[0] == 0xFFFFU ? 0 : p->opta[2]);
0N/A
2693N/A Y0 = p -> opta[1] * y0;
6271N/A Y1 = (Input[1] == 0xFFFFU ? 0 : p->opta[1]);
0N/A
2693N/A Z0 = p -> opta[0] * z0;
6271N/A Z1 = (Input[2] == 0xFFFFU ? 0 : p->opta[0]);
0N/A
6271N/A LutTable = &LutTable[X0+Y0+Z0];
2693N/A
6271N/A // Output should be computed as x = ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest))
6271N/A // which expands as: x = (Rest + ((Rest+0x7fff)/0xFFFF) + 0x8000)>>16
6271N/A // This can be replaced by: t = Rest+0x8001, x = (t + (t>>16))>>16
6271N/A // at the cost of being off by one at 7fff and 17ffe.
0N/A
6271N/A if (rx >= ry) {
6271N/A if (ry >= rz) {
6271N/A Y1 += X1;
6271N/A Z1 += Y1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c3 -= c2;
6271N/A c2 -= c1;
6271N/A c1 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A } else if (rz >= rx) {
6271N/A X1 += Z1;
6271N/A Y1 += X1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c2 -= c1;
6271N/A c1 -= c3;
6271N/A c3 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A } else {
6271N/A Z1 += X1;
6271N/A Y1 += Z1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c2 -= c3;
6271N/A c3 -= c1;
6271N/A c1 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A }
6271N/A } else {
6271N/A if (rx >= rz) {
6271N/A X1 += Y1;
6271N/A Z1 += X1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c3 -= c1;
6271N/A c1 -= c2;
6271N/A c2 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A } else if (ry >= rz) {
6271N/A Z1 += Y1;
6271N/A X1 += Z1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c1 -= c3;
6271N/A c3 -= c2;
6271N/A c2 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A } else {
6271N/A Y1 += Z1;
6271N/A X1 += Y1;
6271N/A for (; TotalOut; TotalOut--) {
6271N/A c1 = LutTable[X1];
6271N/A c2 = LutTable[Y1];
6271N/A c3 = LutTable[Z1];
6271N/A c0 = *LutTable++;
6271N/A c1 -= c2;
6271N/A c2 -= c3;
6271N/A c3 -= c0;
6271N/A Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
6271N/A *Output++ = (cmsUInt16Number) c0 + ((Rest + (Rest>>16))>>16);
6271N/A }
6271N/A }
2693N/A }
2693N/A}
2693N/A
0N/A
2693N/A#define DENS(i,j,k) (LutTable[(i)+(j)+(k)+OutChan])
2693N/Astatic
2693N/Avoid Eval4Inputs(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p16)
2693N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, rk;
2693N/A int K0, K1;
2693N/A cmsS15Fixed16Number fx, fy, fz;
2693N/A cmsS15Fixed16Number rx, ry, rz;
2693N/A int x0, y0, z0;
2693N/A cmsS15Fixed16Number X0, X1, Y0, Y1, Z0, Z1;
2693N/A cmsUInt32Number i;
2693N/A cmsS15Fixed16Number c0, c1, c2, c3, Rest;
2693N/A cmsUInt32Number OutChan;
2693N/A cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A
2693N/A
2693N/A fk = _cmsToFixedDomain((int) Input[0] * p16 -> Domain[0]);
2693N/A fx = _cmsToFixedDomain((int) Input[1] * p16 -> Domain[1]);
2693N/A fy = _cmsToFixedDomain((int) Input[2] * p16 -> Domain[2]);
2693N/A fz = _cmsToFixedDomain((int) Input[3] * p16 -> Domain[3]);
2693N/A
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A x0 = FIXED_TO_INT(fx);
2693N/A y0 = FIXED_TO_INT(fy);
2693N/A z0 = FIXED_TO_INT(fz);
2693N/A
2693N/A rk = FIXED_REST_TO_INT(fk);
2693N/A rx = FIXED_REST_TO_INT(fx);
2693N/A ry = FIXED_REST_TO_INT(fy);
2693N/A rz = FIXED_REST_TO_INT(fz);
2693N/A
2693N/A K0 = p16 -> opta[3] * k0;
2693N/A K1 = K0 + (Input[0] == 0xFFFFU ? 0 : p16->opta[3]);
0N/A
2693N/A X0 = p16 -> opta[2] * x0;
2693N/A X1 = X0 + (Input[1] == 0xFFFFU ? 0 : p16->opta[2]);
2693N/A
2693N/A Y0 = p16 -> opta[1] * y0;
2693N/A Y1 = Y0 + (Input[2] == 0xFFFFU ? 0 : p16->opta[1]);
2693N/A
2693N/A Z0 = p16 -> opta[0] * z0;
2693N/A Z1 = Z0 + (Input[3] == 0xFFFFU ? 0 : p16->opta[0]);
2693N/A
2693N/A LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A LutTable += K0;
2693N/A
2693N/A for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
2693N/A
2693N/A c0 = DENS(X0, Y0, Z0);
2693N/A
2693N/A if (rx >= ry && ry >= rz) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rx >= rz && rz >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rz >= rx && rx >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
2693N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rx && rx >= rz) {
0N/A
2693N/A c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rz && rz >= rx) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rz >= ry && ry >= rx) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
2693N/A
2693N/A }
2693N/A else {
2693N/A c1 = c2 = c3 = 0;
2693N/A }
2693N/A
2693N/A Rest = c1 * rx + c2 * ry + c3 * rz;
2693N/A
2693N/A Tmp1[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
2693N/A }
2693N/A
2693N/A
2693N/A LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A LutTable += K1;
2693N/A
2693N/A for (OutChan=0; OutChan < p16 -> nOutputs; OutChan++) {
2693N/A
2693N/A c0 = DENS(X0, Y0, Z0);
2693N/A
2693N/A if (rx >= ry && ry >= rz) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rx >= rz && rz >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z0) - c0;
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rz >= rx && rx >= ry) {
2693N/A
2693N/A c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
2693N/A c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
2693N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rx && rx >= rz) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (ry >= rz && rz >= rx) {
0N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z0) - c0;
2693N/A c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
2693N/A
2693N/A }
2693N/A else
2693N/A if (rz >= ry && ry >= rx) {
2693N/A
2693N/A c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
2693N/A c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
2693N/A c3 = DENS(X0, Y0, Z1) - c0;
2693N/A
2693N/A }
2693N/A else {
2693N/A c1 = c2 = c3 = 0;
2693N/A }
2693N/A
2693N/A Rest = c1 * rx + c2 * ry + c3 * rz;
2693N/A
2693N/A Tmp2[OutChan] = (cmsUInt16Number) c0 + ROUND_FIXED_TO_INT(_cmsToFixedDomain(Rest));
2693N/A }
2693N/A
2693N/A
2693N/A
2693N/A for (i=0; i < p16 -> nOutputs; i++) {
2693N/A Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
2693N/A }
2693N/A}
2693N/A#undef DENS
2693N/A
2693N/A
2693N/A// For more that 3 inputs (i.e., CMYK)
2693N/A// evaluate two 3-dimensional interpolations and then linearly interpolate between them.
2693N/A
0N/A
2693N/Astatic
2693N/Avoid Eval4InputsFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number rest;
2693N/A cmsFloat32Number pk;
2693N/A int k0, K0, K1;
2693N/A const cmsFloat32Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
2693N/A
2693N/A
2693N/A pk = Input[0] * p->Domain[0];
2693N/A k0 = _cmsQuickFloor(pk);
2693N/A rest = pk - (cmsFloat32Number) k0;
0N/A
2693N/A K0 = p -> opta[3] * k0;
2693N/A K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[3]);
2693N/A
2693N/A p1 = *p;
2693N/A memmove(&p1.Domain[0], &p ->Domain[1], 3*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A TetrahedralInterpFloat(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A TetrahedralInterpFloat(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p -> nOutputs; i++)
2693N/A {
2693N/A cmsFloat32Number y0 = Tmp1[i];
2693N/A cmsFloat32Number y1 = Tmp2[i];
2693N/A
2693N/A Output[i] = y0 + (y1 - y0) * rest;
0N/A }
2693N/A}
2693N/A
2693N/A
2693N/Astatic
2693N/Avoid Eval5Inputs(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
0N/A
2693N/A register const cmsInterpParams* p16)
2693N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, rk;
2693N/A int K0, K1;
2693N/A const cmsUInt16Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
0N/A
0N/A
2693N/A fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A rk = FIXED_REST_TO_INT(fk);
0N/A
2693N/A K0 = p16 -> opta[4] * k0;
2693N/A K1 = p16 -> opta[4] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
2693N/A
2693N/A p1 = *p16;
2693N/A memmove(&p1.Domain[0], &p16 ->Domain[1], 4*sizeof(cmsUInt32Number));
0N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval4Inputs(Input + 1, Tmp1, &p1);
0N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval4Inputs(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p16 -> nOutputs; i++) {
2693N/A
2693N/A Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
0N/A }
0N/A
2693N/A}
2693N/A
2693N/A
2693N/Astatic
2693N/Avoid Eval5InputsFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number rest;
2693N/A cmsFloat32Number pk;
2693N/A int k0, K0, K1;
2693N/A const cmsFloat32Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
2693N/A
2693N/A pk = Input[0] * p->Domain[0];
2693N/A k0 = _cmsQuickFloor(pk);
2693N/A rest = pk - (cmsFloat32Number) k0;
0N/A
2693N/A K0 = p -> opta[4] * k0;
2693N/A K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[4]);
2693N/A
2693N/A p1 = *p;
2693N/A memmove(&p1.Domain[0], &p ->Domain[1], 4*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval4InputsFloat(Input + 1, Tmp1, &p1);
0N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval4InputsFloat(Input + 1, Tmp2, &p1);
0N/A
2693N/A for (i=0; i < p -> nOutputs; i++) {
0N/A
2693N/A cmsFloat32Number y0 = Tmp1[i];
2693N/A cmsFloat32Number y1 = Tmp2[i];
2693N/A
2693N/A Output[i] = y0 + (y1 - y0) * rest;
2693N/A }
0N/A}
0N/A
0N/A
0N/A
2693N/Astatic
2693N/Avoid Eval6Inputs(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p16)
2693N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, rk;
2693N/A int K0, K1;
2693N/A const cmsUInt16Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
2693N/A
2693N/A fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A rk = FIXED_REST_TO_INT(fk);
2693N/A
2693N/A K0 = p16 -> opta[5] * k0;
2693N/A K1 = p16 -> opta[5] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
2693N/A
2693N/A p1 = *p16;
2693N/A memmove(&p1.Domain[0], &p16 ->Domain[1], 5*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval5Inputs(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval5Inputs(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p16 -> nOutputs; i++) {
2693N/A
2693N/A Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
2693N/A }
2693N/A
2693N/A}
2693N/A
0N/A
2693N/Astatic
2693N/Avoid Eval6InputsFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number rest;
2693N/A cmsFloat32Number pk;
2693N/A int k0, K0, K1;
2693N/A const cmsFloat32Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
2693N/A
2693N/A pk = Input[0] * p->Domain[0];
2693N/A k0 = _cmsQuickFloor(pk);
2693N/A rest = pk - (cmsFloat32Number) k0;
2693N/A
2693N/A K0 = p -> opta[5] * k0;
2693N/A K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[5]);
2693N/A
2693N/A p1 = *p;
2693N/A memmove(&p1.Domain[0], &p ->Domain[1], 5*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval5InputsFloat(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval5InputsFloat(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p -> nOutputs; i++) {
2693N/A
2693N/A cmsFloat32Number y0 = Tmp1[i];
2693N/A cmsFloat32Number y1 = Tmp2[i];
2693N/A
2693N/A Output[i] = y0 + (y1 - y0) * rest;
2693N/A }
2693N/A}
2693N/A
2693N/A
2693N/Astatic
2693N/Avoid Eval7Inputs(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p16)
2693N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, rk;
2693N/A int K0, K1;
2693N/A const cmsUInt16Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
0N/A
0N/A
2693N/A fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A rk = FIXED_REST_TO_INT(fk);
2693N/A
2693N/A K0 = p16 -> opta[6] * k0;
2693N/A K1 = p16 -> opta[6] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
0N/A
2693N/A p1 = *p16;
6271N/A memmove(&p1.Domain[0], &p16 ->Domain[1], 6*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval6Inputs(Input + 1, Tmp1, &p1);
0N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval6Inputs(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p16 -> nOutputs; i++) {
2693N/A Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
2693N/A }
2693N/A}
2693N/A
2693N/A
2693N/Astatic
2693N/Avoid Eval7InputsFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
0N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number rest;
2693N/A cmsFloat32Number pk;
2693N/A int k0, K0, K1;
2693N/A const cmsFloat32Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
0N/A
2693N/A pk = Input[0] * p->Domain[0];
2693N/A k0 = _cmsQuickFloor(pk);
2693N/A rest = pk - (cmsFloat32Number) k0;
2693N/A
2693N/A K0 = p -> opta[6] * k0;
2693N/A K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[6]);
2693N/A
2693N/A p1 = *p;
2693N/A memmove(&p1.Domain[0], &p ->Domain[1], 6*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval6InputsFloat(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval6InputsFloat(Input + 1, Tmp2, &p1);
2693N/A
2693N/A
2693N/A for (i=0; i < p -> nOutputs; i++) {
2693N/A
2693N/A cmsFloat32Number y0 = Tmp1[i];
2693N/A cmsFloat32Number y1 = Tmp2[i];
2693N/A
2693N/A Output[i] = y0 + (y1 - y0) * rest;
2693N/A
2693N/A }
2693N/A}
2693N/A
2693N/Astatic
2693N/Avoid Eval8Inputs(register const cmsUInt16Number Input[],
2693N/A register cmsUInt16Number Output[],
2693N/A register const cmsInterpParams* p16)
2693N/A{
2693N/A const cmsUInt16Number* LutTable = (cmsUInt16Number*) p16 -> Table;
2693N/A cmsS15Fixed16Number fk;
2693N/A cmsS15Fixed16Number k0, rk;
2693N/A int K0, K1;
2693N/A const cmsUInt16Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsUInt16Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
2693N/A
2693N/A fk = _cmsToFixedDomain((cmsS15Fixed16Number) Input[0] * p16 -> Domain[0]);
2693N/A k0 = FIXED_TO_INT(fk);
2693N/A rk = FIXED_REST_TO_INT(fk);
2693N/A
2693N/A K0 = p16 -> opta[7] * k0;
2693N/A K1 = p16 -> opta[7] * (k0 + (Input[0] != 0xFFFFU ? 1 : 0));
2693N/A
2693N/A p1 = *p16;
2693N/A memmove(&p1.Domain[0], &p16 ->Domain[1], 7*sizeof(cmsUInt32Number));
2693N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval7Inputs(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A Eval7Inputs(Input + 1, Tmp2, &p1);
2693N/A
2693N/A for (i=0; i < p16 -> nOutputs; i++) {
2693N/A Output[i] = LinearInterp(rk, Tmp1[i], Tmp2[i]);
2693N/A }
2693N/A}
0N/A
0N/A
0N/A
2693N/Astatic
2693N/Avoid Eval8InputsFloat(const cmsFloat32Number Input[],
2693N/A cmsFloat32Number Output[],
2693N/A const cmsInterpParams* p)
2693N/A{
2693N/A const cmsFloat32Number* LutTable = (cmsFloat32Number*) p -> Table;
2693N/A cmsFloat32Number rest;
2693N/A cmsFloat32Number pk;
2693N/A int k0, K0, K1;
2693N/A const cmsFloat32Number* T;
2693N/A cmsUInt32Number i;
2693N/A cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
2693N/A cmsInterpParams p1;
0N/A
2693N/A pk = Input[0] * p->Domain[0];
2693N/A k0 = _cmsQuickFloor(pk);
2693N/A rest = pk - (cmsFloat32Number) k0;
2693N/A
2693N/A K0 = p -> opta[7] * k0;
2693N/A K1 = K0 + (Input[0] >= 1.0 ? 0 : p->opta[7]);
2693N/A
2693N/A p1 = *p;
2693N/A memmove(&p1.Domain[0], &p ->Domain[1], 7*sizeof(cmsUInt32Number));
0N/A
2693N/A T = LutTable + K0;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval7InputsFloat(Input + 1, Tmp1, &p1);
2693N/A
2693N/A T = LutTable + K1;
2693N/A p1.Table = T;
2693N/A
2693N/A Eval7InputsFloat(Input + 1, Tmp2, &p1);
0N/A
0N/A
2693N/A for (i=0; i < p -> nOutputs; i++) {
0N/A
2693N/A cmsFloat32Number y0 = Tmp1[i];
2693N/A cmsFloat32Number y1 = Tmp2[i];
0N/A
2693N/A Output[i] = y0 + (y1 - y0) * rest;
0N/A }
2693N/A}
2693N/A
2693N/A// The default factory
2693N/Astatic
2693N/AcmsInterpFunction DefaultInterpolatorsFactory(cmsUInt32Number nInputChannels, cmsUInt32Number nOutputChannels, cmsUInt32Number dwFlags)
2693N/A{
0N/A
2693N/A cmsInterpFunction Interpolation;
2693N/A cmsBool IsFloat = (dwFlags & CMS_LERP_FLAGS_FLOAT);
2693N/A cmsBool IsTrilinear = (dwFlags & CMS_LERP_FLAGS_TRILINEAR);
2693N/A
2693N/A memset(&Interpolation, 0, sizeof(Interpolation));
0N/A
2693N/A // Safety check
2693N/A if (nInputChannels >= 4 && nOutputChannels >= MAX_STAGE_CHANNELS)
2693N/A return Interpolation;
2693N/A
2693N/A switch (nInputChannels) {
0N/A
2693N/A case 1: // Gray LUT / linear
2693N/A
2693N/A if (nOutputChannels == 1) {
2693N/A
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = LinLerp1Dfloat;
2693N/A else
2693N/A Interpolation.Lerp16 = LinLerp1D;
0N/A
2693N/A }
2693N/A else {
0N/A
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval1InputFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval1Input;
2693N/A }
2693N/A break;
0N/A
6271N/A case 2: // Duotone
6271N/A if (IsFloat)
6271N/A Interpolation.LerpFloat = BilinearInterpFloat;
6271N/A else
6271N/A Interpolation.Lerp16 = BilinearInterp16;
6271N/A break;
0N/A
2693N/A case 3: // RGB et al
2693N/A
2693N/A if (IsTrilinear) {
2693N/A
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = TrilinearInterpFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = TrilinearInterp16;
2693N/A }
2693N/A else {
2693N/A
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = TetrahedralInterpFloat;
2693N/A else {
2693N/A
2693N/A Interpolation.Lerp16 = TetrahedralInterp16;
2693N/A }
2693N/A }
2693N/A break;
2693N/A
2693N/A case 4: // CMYK lut
2693N/A
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval4InputsFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval4Inputs;
2693N/A break;
0N/A
2693N/A case 5: // 5 Inks
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval5InputsFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval5Inputs;
2693N/A break;
2693N/A
2693N/A case 6: // 6 Inks
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval6InputsFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval6Inputs;
2693N/A break;
2693N/A
2693N/A case 7: // 7 inks
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval7InputsFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval7Inputs;
2693N/A break;
2693N/A
2693N/A case 8: // 8 inks
2693N/A if (IsFloat)
2693N/A Interpolation.LerpFloat = Eval8InputsFloat;
2693N/A else
2693N/A Interpolation.Lerp16 = Eval8Inputs;
2693N/A break;
2693N/A
2693N/A break;
2693N/A
2693N/A default:
2693N/A Interpolation.Lerp16 = NULL;
0N/A }
0N/A
2693N/A return Interpolation;
0N/A}