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