Home | History | Annotate | Download | only in src
      1 //---------------------------------------------------------------------------------
      2 //
      3 //  Little Color Management System
      4 //  Copyright (c) 1998-2016 Marti Maria Saguer
      5 //
      6 // Permission is hereby granted, free of charge, to any person obtaining
      7 // a copy of this software and associated documentation files (the "Software"),
      8 // to deal in the Software without restriction, including without limitation
      9 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10 // and/or sell copies of the Software, and to permit persons to whom the Software
     11 // is furnished to do so, subject to the following conditions:
     12 //
     13 // The above copyright notice and this permission notice shall be included in
     14 // all copies or substantial portions of the Software.
     15 //
     16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
     18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23 //
     24 //---------------------------------------------------------------------------------
     25 //
     26 
     27 #include "lcms2_internal.h"
     28 
     29 
     30 // Allocates an empty multi profile element
     31 cmsStage* CMSEXPORT _cmsStageAllocPlaceholder(cmsContext ContextID,
     32                                 cmsStageSignature Type,
     33                                 cmsUInt32Number InputChannels,
     34                                 cmsUInt32Number OutputChannels,
     35                                 _cmsStageEvalFn     EvalPtr,
     36                                 _cmsStageDupElemFn  DupElemPtr,
     37                                 _cmsStageFreeElemFn FreePtr,
     38                                 void*             Data)
     39 {
     40     cmsStage* ph = (cmsStage*) _cmsMallocZero(ContextID, sizeof(cmsStage));
     41 
     42     if (ph == NULL) return NULL;
     43 
     44 
     45     ph ->ContextID = ContextID;
     46 
     47     ph ->Type       = Type;
     48     ph ->Implements = Type;   // By default, no clue on what is implementing
     49 
     50     ph ->InputChannels  = InputChannels;
     51     ph ->OutputChannels = OutputChannels;
     52     ph ->EvalPtr        = EvalPtr;
     53     ph ->DupElemPtr     = DupElemPtr;
     54     ph ->FreePtr        = FreePtr;
     55     ph ->Data           = Data;
     56 
     57     return ph;
     58 }
     59 
     60 
     61 static
     62 void EvaluateIdentity(const cmsFloat32Number In[],
     63                             cmsFloat32Number Out[],
     64                       const cmsStage *mpe)
     65 {
     66     memmove(Out, In, mpe ->InputChannels * sizeof(cmsFloat32Number));
     67 }
     68 
     69 
     70 cmsStage* CMSEXPORT cmsStageAllocIdentity(cmsContext ContextID, cmsUInt32Number nChannels)
     71 {
     72     return _cmsStageAllocPlaceholder(ContextID,
     73                                    cmsSigIdentityElemType,
     74                                    nChannels, nChannels,
     75                                    EvaluateIdentity,
     76                                    NULL,
     77                                    NULL,
     78                                    NULL);
     79  }
     80 
     81 // Conversion functions. From floating point to 16 bits
     82 static
     83 void FromFloatTo16(const cmsFloat32Number In[], cmsUInt16Number Out[], cmsUInt32Number n)
     84 {
     85     cmsUInt32Number i;
     86 
     87     for (i=0; i < n; i++) {
     88         Out[i] = _cmsQuickSaturateWord(In[i] * 65535.0);
     89     }
     90 }
     91 
     92 // From 16 bits to floating point
     93 static
     94 void From16ToFloat(const cmsUInt16Number In[], cmsFloat32Number Out[], cmsUInt32Number n)
     95 {
     96     cmsUInt32Number i;
     97 
     98     for (i=0; i < n; i++) {
     99         Out[i] = (cmsFloat32Number) In[i] / 65535.0F;
    100     }
    101 }
    102 
    103 
    104 // This function is quite useful to analyze the structure of a LUT and retrieve the MPE elements
    105 // that conform the LUT. It should be called with the LUT, the number of expected elements and
    106 // then a list of expected types followed with a list of cmsFloat64Number pointers to MPE elements. If
    107 // the function founds a match with current pipeline, it fills the pointers and returns TRUE
    108 // if not, returns FALSE without touching anything. Setting pointers to NULL does bypass
    109 // the storage process.
    110 cmsBool  CMSEXPORT cmsPipelineCheckAndRetreiveStages(const cmsPipeline* Lut, cmsUInt32Number n, ...)
    111 {
    112     va_list args;
    113     cmsUInt32Number i;
    114     cmsStage* mpe;
    115     cmsStageSignature Type;
    116     void** ElemPtr;
    117 
    118     // Make sure same number of elements
    119     if (cmsPipelineStageCount(Lut) != n) return FALSE;
    120 
    121     va_start(args, n);
    122 
    123     // Iterate across asked types
    124     mpe = Lut ->Elements;
    125     for (i=0; i < n; i++) {
    126 
    127         // Get asked type
    128         Type  = (cmsStageSignature)va_arg(args, cmsStageSignature);
    129         if (mpe ->Type != Type) {
    130 
    131             va_end(args);       // Mismatch. We are done.
    132             return FALSE;
    133         }
    134         mpe = mpe ->Next;
    135     }
    136 
    137     // Found a combination, fill pointers if not NULL
    138     mpe = Lut ->Elements;
    139     for (i=0; i < n; i++) {
    140 
    141         ElemPtr = va_arg(args, void**);
    142         if (ElemPtr != NULL)
    143             *ElemPtr = mpe;
    144 
    145         mpe = mpe ->Next;
    146     }
    147 
    148     va_end(args);
    149     return TRUE;
    150 }
    151 
    152 // Below there are implementations for several types of elements. Each type may be implemented by a
    153 // evaluation function, a duplication function, a function to free resources and a constructor.
    154 
    155 // *************************************************************************************************
    156 // Type cmsSigCurveSetElemType (curves)
    157 // *************************************************************************************************
    158 
    159 cmsToneCurve** _cmsStageGetPtrToCurveSet(const cmsStage* mpe)
    160 {
    161     _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
    162 
    163     return Data ->TheCurves;
    164 }
    165 
    166 static
    167 void EvaluateCurves(const cmsFloat32Number In[],
    168                     cmsFloat32Number Out[],
    169                     const cmsStage *mpe)
    170 {
    171     _cmsStageToneCurvesData* Data;
    172     cmsUInt32Number i;
    173 
    174     _cmsAssert(mpe != NULL);
    175 
    176     Data = (_cmsStageToneCurvesData*) mpe ->Data;
    177     if (Data == NULL) return;
    178 
    179     if (Data ->TheCurves == NULL) return;
    180 
    181     for (i=0; i < Data ->nCurves; i++) {
    182         Out[i] = cmsEvalToneCurveFloat(Data ->TheCurves[i], In[i]);
    183     }
    184 }
    185 
    186 static
    187 void CurveSetElemTypeFree(cmsStage* mpe)
    188 {
    189     _cmsStageToneCurvesData* Data;
    190     cmsUInt32Number i;
    191 
    192     _cmsAssert(mpe != NULL);
    193 
    194     Data = (_cmsStageToneCurvesData*) mpe ->Data;
    195     if (Data == NULL) return;
    196 
    197     if (Data ->TheCurves != NULL) {
    198         for (i=0; i < Data ->nCurves; i++) {
    199             if (Data ->TheCurves[i] != NULL)
    200                 cmsFreeToneCurve(Data ->TheCurves[i]);
    201         }
    202     }
    203     _cmsFree(mpe ->ContextID, Data ->TheCurves);
    204     _cmsFree(mpe ->ContextID, Data);
    205 }
    206 
    207 
    208 static
    209 void* CurveSetDup(cmsStage* mpe)
    210 {
    211     _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) mpe ->Data;
    212     _cmsStageToneCurvesData* NewElem;
    213     cmsUInt32Number i;
    214 
    215     NewElem = (_cmsStageToneCurvesData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageToneCurvesData));
    216     if (NewElem == NULL) return NULL;
    217 
    218     NewElem ->nCurves   = Data ->nCurves;
    219     NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(mpe ->ContextID, NewElem ->nCurves, sizeof(cmsToneCurve*));
    220 
    221     if (NewElem ->TheCurves == NULL) goto Error;
    222 
    223     for (i=0; i < NewElem ->nCurves; i++) {
    224 
    225         // Duplicate each curve. It may fail.
    226         NewElem ->TheCurves[i] = cmsDupToneCurve(Data ->TheCurves[i]);
    227         if (NewElem ->TheCurves[i] == NULL) goto Error;
    228 
    229 
    230     }
    231     return (void*) NewElem;
    232 
    233 Error:
    234 
    235     if (NewElem ->TheCurves != NULL) {
    236         for (i=0; i < NewElem ->nCurves; i++) {
    237             if (NewElem ->TheCurves[i])
    238                 cmsFreeToneCurve(NewElem ->TheCurves[i]);
    239         }
    240     }
    241     _cmsFree(mpe ->ContextID, NewElem ->TheCurves);
    242     _cmsFree(mpe ->ContextID, NewElem);
    243     return NULL;
    244 }
    245 
    246 
    247 // Curves == NULL forces identity curves
    248 cmsStage* CMSEXPORT cmsStageAllocToneCurves(cmsContext ContextID, cmsUInt32Number nChannels, cmsToneCurve* const Curves[])
    249 {
    250     cmsUInt32Number i;
    251     _cmsStageToneCurvesData* NewElem;
    252     cmsStage* NewMPE;
    253 
    254 
    255     NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCurveSetElemType, nChannels, nChannels,
    256                                      EvaluateCurves, CurveSetDup, CurveSetElemTypeFree, NULL );
    257     if (NewMPE == NULL) return NULL;
    258 
    259     NewElem = (_cmsStageToneCurvesData*) _cmsMallocZero(ContextID, sizeof(_cmsStageToneCurvesData));
    260     if (NewElem == NULL) {
    261         cmsStageFree(NewMPE);
    262         return NULL;
    263     }
    264 
    265     NewMPE ->Data  = (void*) NewElem;
    266 
    267     NewElem ->nCurves   = nChannels;
    268     NewElem ->TheCurves = (cmsToneCurve**) _cmsCalloc(ContextID, nChannels, sizeof(cmsToneCurve*));
    269     if (NewElem ->TheCurves == NULL) {
    270         cmsStageFree(NewMPE);
    271         return NULL;
    272     }
    273 
    274     for (i=0; i < nChannels; i++) {
    275 
    276         if (Curves == NULL) {
    277             NewElem ->TheCurves[i] = cmsBuildGamma(ContextID, 1.0);
    278         }
    279         else {
    280             NewElem ->TheCurves[i] = cmsDupToneCurve(Curves[i]);
    281         }
    282 
    283         if (NewElem ->TheCurves[i] == NULL) {
    284             cmsStageFree(NewMPE);
    285             return NULL;
    286         }
    287 
    288     }
    289 
    290    return NewMPE;
    291 }
    292 
    293 
    294 // Create a bunch of identity curves
    295 cmsStage* _cmsStageAllocIdentityCurves(cmsContext ContextID, int nChannels)
    296 {
    297     cmsStage* mpe = cmsStageAllocToneCurves(ContextID, nChannels, NULL);
    298 
    299     if (mpe == NULL) return NULL;
    300     mpe ->Implements = cmsSigIdentityElemType;
    301     return mpe;
    302 }
    303 
    304 
    305 // *************************************************************************************************
    306 // Type cmsSigMatrixElemType (Matrices)
    307 // *************************************************************************************************
    308 
    309 
    310 // Special care should be taken here because precision loss. A temporary cmsFloat64Number buffer is being used
    311 static
    312 void EvaluateMatrix(const cmsFloat32Number In[],
    313                     cmsFloat32Number Out[],
    314                     const cmsStage *mpe)
    315 {
    316     cmsUInt32Number i, j;
    317     _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
    318     cmsFloat64Number Tmp;
    319 
    320     // Input is already in 0..1.0 notation
    321     for (i=0; i < mpe ->OutputChannels; i++) {
    322 
    323         Tmp = 0;
    324         for (j=0; j < mpe->InputChannels; j++) {
    325             Tmp += In[j] * Data->Double[i*mpe->InputChannels + j];
    326         }
    327 
    328         if (Data ->Offset != NULL)
    329             Tmp += Data->Offset[i];
    330 
    331         Out[i] = (cmsFloat32Number) Tmp;
    332     }
    333 
    334 
    335     // Output in 0..1.0 domain
    336 }
    337 
    338 
    339 // Duplicate a yet-existing matrix element
    340 static
    341 void* MatrixElemDup(cmsStage* mpe)
    342 {
    343     _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
    344     _cmsStageMatrixData* NewElem;
    345     cmsUInt32Number sz;
    346 
    347     NewElem = (_cmsStageMatrixData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageMatrixData));
    348     if (NewElem == NULL) return NULL;
    349 
    350     sz = mpe ->InputChannels * mpe ->OutputChannels;
    351 
    352     NewElem ->Double = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID, Data ->Double, sz * sizeof(cmsFloat64Number)) ;
    353 
    354     if (Data ->Offset)
    355         NewElem ->Offset = (cmsFloat64Number*) _cmsDupMem(mpe ->ContextID,
    356                                                 Data ->Offset, mpe -> OutputChannels * sizeof(cmsFloat64Number)) ;
    357 
    358     return (void*) NewElem;
    359 }
    360 
    361 
    362 static
    363 void MatrixElemTypeFree(cmsStage* mpe)
    364 {
    365     _cmsStageMatrixData* Data = (_cmsStageMatrixData*) mpe ->Data;
    366     if (Data == NULL)
    367         return;
    368     if (Data ->Double)
    369         _cmsFree(mpe ->ContextID, Data ->Double);
    370 
    371     if (Data ->Offset)
    372         _cmsFree(mpe ->ContextID, Data ->Offset);
    373 
    374     _cmsFree(mpe ->ContextID, mpe ->Data);
    375 }
    376 
    377 
    378 
    379 cmsStage*  CMSEXPORT cmsStageAllocMatrix(cmsContext ContextID, cmsUInt32Number Rows, cmsUInt32Number Cols,
    380                                      const cmsFloat64Number* Matrix, const cmsFloat64Number* Offset)
    381 {
    382     cmsUInt32Number i, n;
    383     _cmsStageMatrixData* NewElem;
    384     cmsStage* NewMPE;
    385 
    386     n = Rows * Cols;
    387 
    388     // Check for overflow
    389     if (n == 0) return NULL;
    390     if (n >= UINT_MAX / Cols) return NULL;
    391     if (n >= UINT_MAX / Rows) return NULL;
    392     if (n < Rows || n < Cols) return NULL;
    393 
    394     NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigMatrixElemType, Cols, Rows,
    395                                      EvaluateMatrix, MatrixElemDup, MatrixElemTypeFree, NULL );
    396     if (NewMPE == NULL) return NULL;
    397 
    398 
    399     NewElem = (_cmsStageMatrixData*) _cmsMallocZero(ContextID, sizeof(_cmsStageMatrixData));
    400     if (NewElem == NULL) return NULL;
    401 
    402 
    403     NewElem ->Double = (cmsFloat64Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat64Number));
    404 
    405     if (NewElem->Double == NULL) {
    406         MatrixElemTypeFree(NewMPE);
    407         return NULL;
    408     }
    409 
    410     for (i=0; i < n; i++) {
    411         NewElem ->Double[i] = Matrix[i];
    412     }
    413 
    414 
    415     if (Offset != NULL) {
    416 
    417         NewElem ->Offset = (cmsFloat64Number*) _cmsCalloc(ContextID, Rows, sizeof(cmsFloat64Number));
    418         if (NewElem->Offset == NULL) {
    419            MatrixElemTypeFree(NewMPE);
    420            return NULL;
    421         }
    422 
    423         for (i=0; i < Rows; i++) {
    424                 NewElem ->Offset[i] = Offset[i];
    425         }
    426 
    427     }
    428 
    429     NewMPE ->Data  = (void*) NewElem;
    430     return NewMPE;
    431 }
    432 
    433 
    434 // *************************************************************************************************
    435 // Type cmsSigCLutElemType
    436 // *************************************************************************************************
    437 
    438 
    439 // Evaluate in true floating point
    440 static
    441 void EvaluateCLUTfloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
    442 {
    443     _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
    444 
    445     Data -> Params ->Interpolation.LerpFloat(In, Out, Data->Params);
    446 }
    447 
    448 
    449 // Convert to 16 bits, evaluate, and back to floating point
    450 static
    451 void EvaluateCLUTfloatIn16(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
    452 {
    453     _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
    454     cmsUInt16Number In16[MAX_STAGE_CHANNELS], Out16[MAX_STAGE_CHANNELS];
    455 
    456     _cmsAssert(mpe ->InputChannels  <= MAX_STAGE_CHANNELS);
    457     _cmsAssert(mpe ->OutputChannels <= MAX_STAGE_CHANNELS);
    458 
    459     FromFloatTo16(In, In16, mpe ->InputChannels);
    460     Data -> Params ->Interpolation.Lerp16(In16, Out16, Data->Params);
    461     From16ToFloat(Out16, Out,  mpe ->OutputChannels);
    462 }
    463 
    464 
    465 // Given an hypercube of b dimensions, with Dims[] number of nodes by dimension, calculate the total amount of nodes
    466 static
    467 cmsUInt32Number CubeSize(const cmsUInt32Number Dims[], cmsUInt32Number b)
    468 {
    469     cmsUInt32Number rv, dim;
    470 
    471     _cmsAssert(Dims != NULL);
    472 
    473     for (rv = 1; b > 0; b--) {
    474 
    475         dim = Dims[b-1];
    476         if (dim == 0) return 0;  // Error
    477 
    478         rv *= dim;
    479 
    480         // Check for overflow
    481         if (rv > UINT_MAX / dim) return 0;
    482     }
    483 
    484     return rv;
    485 }
    486 
    487 static
    488 void* CLUTElemDup(cmsStage* mpe)
    489 {
    490     _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
    491     _cmsStageCLutData* NewElem;
    492 
    493 
    494     NewElem = (_cmsStageCLutData*) _cmsMallocZero(mpe ->ContextID, sizeof(_cmsStageCLutData));
    495     if (NewElem == NULL) return NULL;
    496 
    497     NewElem ->nEntries       = Data ->nEntries;
    498     NewElem ->HasFloatValues = Data ->HasFloatValues;
    499 
    500     if (Data ->Tab.T) {
    501 
    502         if (Data ->HasFloatValues) {
    503             NewElem ->Tab.TFloat = (cmsFloat32Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.TFloat, Data ->nEntries * sizeof (cmsFloat32Number));
    504             if (NewElem ->Tab.TFloat == NULL)
    505                 goto Error;
    506         } else {
    507             NewElem ->Tab.T = (cmsUInt16Number*) _cmsDupMem(mpe ->ContextID, Data ->Tab.T, Data ->nEntries * sizeof (cmsUInt16Number));
    508             if (NewElem ->Tab.T == NULL)
    509                 goto Error;
    510         }
    511     }
    512 
    513     NewElem ->Params   = _cmsComputeInterpParamsEx(mpe ->ContextID,
    514                                                    Data ->Params ->nSamples,
    515                                                    Data ->Params ->nInputs,
    516                                                    Data ->Params ->nOutputs,
    517                                                    NewElem ->Tab.T,
    518                                                    Data ->Params ->dwFlags);
    519     if (NewElem->Params != NULL)
    520         return (void*) NewElem;
    521  Error:
    522     if (NewElem->Tab.T)
    523         // This works for both types
    524         _cmsFree(mpe ->ContextID, NewElem -> Tab.T);
    525     _cmsFree(mpe ->ContextID, NewElem);
    526     return NULL;
    527 }
    528 
    529 
    530 static
    531 void CLutElemTypeFree(cmsStage* mpe)
    532 {
    533 
    534     _cmsStageCLutData* Data = (_cmsStageCLutData*) mpe ->Data;
    535 
    536     // Already empty
    537     if (Data == NULL) return;
    538 
    539     // This works for both types
    540     if (Data -> Tab.T)
    541         _cmsFree(mpe ->ContextID, Data -> Tab.T);
    542 
    543     _cmsFreeInterpParams(Data ->Params);
    544     _cmsFree(mpe ->ContextID, mpe ->Data);
    545 }
    546 
    547 
    548 // Allocates a 16-bit multidimensional CLUT. This is evaluated at 16-bit precision. Table may have different
    549 // granularity on each dimension.
    550 cmsStage* CMSEXPORT cmsStageAllocCLut16bitGranular(cmsContext ContextID,
    551                                          const cmsUInt32Number clutPoints[],
    552                                          cmsUInt32Number inputChan,
    553                                          cmsUInt32Number outputChan,
    554                                          const cmsUInt16Number* Table)
    555 {
    556     cmsUInt32Number i, n;
    557     _cmsStageCLutData* NewElem;
    558     cmsStage* NewMPE;
    559 
    560     _cmsAssert(clutPoints != NULL);
    561 
    562     if (inputChan > MAX_INPUT_DIMENSIONS) {
    563         cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", inputChan, MAX_INPUT_DIMENSIONS);
    564         return NULL;
    565     }
    566 
    567     NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan,
    568                                      EvaluateCLUTfloatIn16, CLUTElemDup, CLutElemTypeFree, NULL );
    569 
    570     if (NewMPE == NULL) return NULL;
    571 
    572     NewElem = (_cmsStageCLutData*) _cmsMallocZero(ContextID, sizeof(_cmsStageCLutData));
    573     if (NewElem == NULL) {
    574         cmsStageFree(NewMPE);
    575         return NULL;
    576     }
    577 
    578     NewMPE ->Data  = (void*) NewElem;
    579 
    580     NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan);
    581     NewElem -> HasFloatValues = FALSE;
    582 
    583     if (n == 0) {
    584         cmsStageFree(NewMPE);
    585         return NULL;
    586     }
    587 
    588 
    589     NewElem ->Tab.T  = (cmsUInt16Number*) _cmsCalloc(ContextID, n, sizeof(cmsUInt16Number));
    590     if (NewElem ->Tab.T == NULL) {
    591         cmsStageFree(NewMPE);
    592         return NULL;
    593     }
    594 
    595     if (Table != NULL) {
    596         for (i=0; i < n; i++) {
    597             NewElem ->Tab.T[i] = Table[i];
    598         }
    599     }
    600 
    601     NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints, inputChan, outputChan, NewElem ->Tab.T, CMS_LERP_FLAGS_16BITS);
    602     if (NewElem ->Params == NULL) {
    603         cmsStageFree(NewMPE);
    604         return NULL;
    605     }
    606 
    607     return NewMPE;
    608 }
    609 
    610 cmsStage* CMSEXPORT cmsStageAllocCLut16bit(cmsContext ContextID,
    611                                     cmsUInt32Number nGridPoints,
    612                                     cmsUInt32Number inputChan,
    613                                     cmsUInt32Number outputChan,
    614                                     const cmsUInt16Number* Table)
    615 {
    616     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
    617     int i;
    618 
    619    // Our resulting LUT would be same gridpoints on all dimensions
    620     for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
    621         Dimensions[i] = nGridPoints;
    622 
    623     return cmsStageAllocCLut16bitGranular(ContextID, Dimensions, inputChan, outputChan, Table);
    624 }
    625 
    626 
    627 cmsStage* CMSEXPORT cmsStageAllocCLutFloat(cmsContext ContextID,
    628                                        cmsUInt32Number nGridPoints,
    629                                        cmsUInt32Number inputChan,
    630                                        cmsUInt32Number outputChan,
    631                                        const cmsFloat32Number* Table)
    632 {
    633    cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
    634    int i;
    635 
    636     // Our resulting LUT would be same gridpoints on all dimensions
    637     for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
    638         Dimensions[i] = nGridPoints;
    639 
    640     return cmsStageAllocCLutFloatGranular(ContextID, Dimensions, inputChan, outputChan, Table);
    641 }
    642 
    643 
    644 
    645 cmsStage* CMSEXPORT cmsStageAllocCLutFloatGranular(cmsContext ContextID, const cmsUInt32Number clutPoints[], cmsUInt32Number inputChan, cmsUInt32Number outputChan, const cmsFloat32Number* Table)
    646 {
    647     cmsUInt32Number i, n;
    648     _cmsStageCLutData* NewElem;
    649     cmsStage* NewMPE;
    650 
    651     _cmsAssert(clutPoints != NULL);
    652 
    653     if (inputChan > MAX_INPUT_DIMENSIONS) {
    654         cmsSignalError(ContextID, cmsERROR_RANGE, "Too many input channels (%d channels, max=%d)", inputChan, MAX_INPUT_DIMENSIONS);
    655         return NULL;
    656     }
    657 
    658     NewMPE = _cmsStageAllocPlaceholder(ContextID, cmsSigCLutElemType, inputChan, outputChan,
    659                                              EvaluateCLUTfloat, CLUTElemDup, CLutElemTypeFree, NULL);
    660     if (NewMPE == NULL) return NULL;
    661 
    662 
    663     NewElem = (_cmsStageCLutData*) _cmsMallocZero(ContextID, sizeof(_cmsStageCLutData));
    664     if (NewElem == NULL) {
    665         cmsStageFree(NewMPE);
    666         return NULL;
    667     }
    668 
    669     NewMPE ->Data  = (void*) NewElem;
    670 
    671     // There is a potential integer overflow on conputing n and nEntries.
    672     NewElem -> nEntries = n = outputChan * CubeSize(clutPoints, inputChan);
    673     NewElem -> HasFloatValues = TRUE;
    674 
    675     if (n == 0) {
    676         cmsStageFree(NewMPE);
    677         return NULL;
    678     }
    679 
    680     NewElem ->Tab.TFloat  = (cmsFloat32Number*) _cmsCalloc(ContextID, n, sizeof(cmsFloat32Number));
    681     if (NewElem ->Tab.TFloat == NULL) {
    682         cmsStageFree(NewMPE);
    683         return NULL;
    684     }
    685 
    686     if (Table != NULL) {
    687         for (i=0; i < n; i++) {
    688             NewElem ->Tab.TFloat[i] = Table[i];
    689         }
    690     }
    691 
    692     NewElem ->Params = _cmsComputeInterpParamsEx(ContextID, clutPoints,  inputChan, outputChan, NewElem ->Tab.TFloat, CMS_LERP_FLAGS_FLOAT);
    693     if (NewElem ->Params == NULL) {
    694         cmsStageFree(NewMPE);
    695         return NULL;
    696     }
    697 
    698     return NewMPE;
    699 }
    700 
    701 
    702 static
    703 int IdentitySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void * Cargo)
    704 {
    705     int nChan = *(int*) Cargo;
    706     int i;
    707 
    708     for (i=0; i < nChan; i++)
    709         Out[i] = In[i];
    710 
    711     return 1;
    712 }
    713 
    714 // Creates an MPE that just copies input to output
    715 cmsStage* _cmsStageAllocIdentityCLut(cmsContext ContextID, int nChan)
    716 {
    717     cmsUInt32Number Dimensions[MAX_INPUT_DIMENSIONS];
    718     cmsStage* mpe ;
    719     int i;
    720 
    721     for (i=0; i < MAX_INPUT_DIMENSIONS; i++)
    722         Dimensions[i] = 2;
    723 
    724     mpe = cmsStageAllocCLut16bitGranular(ContextID, Dimensions, nChan, nChan, NULL);
    725     if (mpe == NULL) return NULL;
    726 
    727     if (!cmsStageSampleCLut16bit(mpe, IdentitySampler, &nChan, 0)) {
    728         cmsStageFree(mpe);
    729         return NULL;
    730     }
    731 
    732     mpe ->Implements = cmsSigIdentityElemType;
    733     return mpe;
    734 }
    735 
    736 
    737 
    738 // Quantize a value 0 <= i < MaxSamples to 0..0xffff
    739 cmsUInt16Number _cmsQuantizeVal(cmsFloat64Number i, int MaxSamples)
    740 {
    741     cmsFloat64Number x;
    742 
    743     x = ((cmsFloat64Number) i * 65535.) / (cmsFloat64Number) (MaxSamples - 1);
    744     return _cmsQuickSaturateWord(x);
    745 }
    746 
    747 
    748 // This routine does a sweep on whole input space, and calls its callback
    749 // function on knots. returns TRUE if all ok, FALSE otherwise.
    750 cmsBool CMSEXPORT cmsStageSampleCLut16bit(cmsStage* mpe, cmsSAMPLER16 Sampler, void * Cargo, cmsUInt32Number dwFlags)
    751 {
    752     int i, t, nTotalPoints, index, rest;
    753     int nInputs, nOutputs;
    754     cmsUInt32Number* nSamples;
    755     cmsUInt16Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
    756     _cmsStageCLutData* clut;
    757 
    758     if (mpe == NULL) return FALSE;
    759 
    760     clut = (_cmsStageCLutData*) mpe->Data;
    761 
    762     if (clut == NULL) return FALSE;
    763 
    764     nSamples = clut->Params ->nSamples;
    765     nInputs  = clut->Params ->nInputs;
    766     nOutputs = clut->Params ->nOutputs;
    767 
    768     if (nInputs <= 0) return FALSE;
    769     if (nOutputs <= 0) return FALSE;
    770     if (nInputs > MAX_INPUT_DIMENSIONS) return FALSE;
    771     if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
    772 
    773     nTotalPoints = CubeSize(nSamples, nInputs);
    774     if (nTotalPoints == 0) return FALSE;
    775 
    776     index = 0;
    777     for (i = 0; i < nTotalPoints; i++) {
    778 
    779         rest = i;
    780         for (t = nInputs-1; t >=0; --t) {
    781 
    782             cmsUInt32Number  Colorant = rest % nSamples[t];
    783 
    784             rest /= nSamples[t];
    785 
    786             In[t] = _cmsQuantizeVal(Colorant, nSamples[t]);
    787         }
    788 
    789         if (clut ->Tab.T != NULL) {
    790             for (t=0; t < nOutputs; t++)
    791                 Out[t] = clut->Tab.T[index + t];
    792         }
    793 
    794         if (!Sampler(In, Out, Cargo))
    795             return FALSE;
    796 
    797         if (!(dwFlags & SAMPLER_INSPECT)) {
    798 
    799             if (clut ->Tab.T != NULL) {
    800                 for (t=0; t < nOutputs; t++)
    801                     clut->Tab.T[index + t] = Out[t];
    802             }
    803         }
    804 
    805         index += nOutputs;
    806     }
    807 
    808     return TRUE;
    809 }
    810 
    811 // Same as anterior, but for floting point
    812 cmsBool CMSEXPORT cmsStageSampleCLutFloat(cmsStage* mpe, cmsSAMPLERFLOAT Sampler, void * Cargo, cmsUInt32Number dwFlags)
    813 {
    814     int i, t, nTotalPoints, index, rest;
    815     int nInputs, nOutputs;
    816     cmsUInt32Number* nSamples;
    817     cmsFloat32Number In[MAX_INPUT_DIMENSIONS+1], Out[MAX_STAGE_CHANNELS];
    818     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe->Data;
    819 
    820     nSamples = clut->Params ->nSamples;
    821     nInputs  = clut->Params ->nInputs;
    822     nOutputs = clut->Params ->nOutputs;
    823 
    824     if (nInputs <= 0) return FALSE;
    825     if (nOutputs <= 0) return FALSE;
    826     if (nInputs  > MAX_INPUT_DIMENSIONS) return FALSE;
    827     if (nOutputs >= MAX_STAGE_CHANNELS) return FALSE;
    828 
    829     nTotalPoints = CubeSize(nSamples, nInputs);
    830     if (nTotalPoints == 0) return FALSE;
    831 
    832     index = 0;
    833     for (i = 0; i < nTotalPoints; i++) {
    834 
    835         rest = i;
    836         for (t = nInputs-1; t >=0; --t) {
    837 
    838             cmsUInt32Number  Colorant = rest % nSamples[t];
    839 
    840             rest /= nSamples[t];
    841 
    842             In[t] =  (cmsFloat32Number) (_cmsQuantizeVal(Colorant, nSamples[t]) / 65535.0);
    843         }
    844 
    845         if (clut ->Tab.TFloat != NULL) {
    846             for (t=0; t < nOutputs; t++)
    847                 Out[t] = clut->Tab.TFloat[index + t];
    848         }
    849 
    850         if (!Sampler(In, Out, Cargo))
    851             return FALSE;
    852 
    853         if (!(dwFlags & SAMPLER_INSPECT)) {
    854 
    855             if (clut ->Tab.TFloat != NULL) {
    856                 for (t=0; t < nOutputs; t++)
    857                     clut->Tab.TFloat[index + t] = Out[t];
    858             }
    859         }
    860 
    861         index += nOutputs;
    862     }
    863 
    864     return TRUE;
    865 }
    866 
    867 
    868 
    869 // This routine does a sweep on whole input space, and calls its callback
    870 // function on knots. returns TRUE if all ok, FALSE otherwise.
    871 cmsBool CMSEXPORT cmsSliceSpace16(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
    872                                          cmsSAMPLER16 Sampler, void * Cargo)
    873 {
    874     int i, t, nTotalPoints, rest;
    875     cmsUInt16Number In[cmsMAXCHANNELS];
    876 
    877     if (nInputs >= cmsMAXCHANNELS) return FALSE;
    878 
    879     nTotalPoints = CubeSize(clutPoints, nInputs);
    880     if (nTotalPoints == 0) return FALSE;
    881 
    882     for (i = 0; i < nTotalPoints; i++) {
    883 
    884         rest = i;
    885         for (t = nInputs-1; t >=0; --t) {
    886 
    887             cmsUInt32Number  Colorant = rest % clutPoints[t];
    888 
    889             rest /= clutPoints[t];
    890             In[t] = _cmsQuantizeVal(Colorant, clutPoints[t]);
    891 
    892         }
    893 
    894         if (!Sampler(In, NULL, Cargo))
    895             return FALSE;
    896     }
    897 
    898     return TRUE;
    899 }
    900 
    901 cmsInt32Number CMSEXPORT cmsSliceSpaceFloat(cmsUInt32Number nInputs, const cmsUInt32Number clutPoints[],
    902                                             cmsSAMPLERFLOAT Sampler, void * Cargo)
    903 {
    904     int i, t, nTotalPoints, rest;
    905     cmsFloat32Number In[cmsMAXCHANNELS];
    906 
    907     if (nInputs >= cmsMAXCHANNELS) return FALSE;
    908 
    909     nTotalPoints = CubeSize(clutPoints, nInputs);
    910     if (nTotalPoints == 0) return FALSE;
    911 
    912     for (i = 0; i < nTotalPoints; i++) {
    913 
    914         rest = i;
    915         for (t = nInputs-1; t >=0; --t) {
    916 
    917             cmsUInt32Number  Colorant = rest % clutPoints[t];
    918 
    919             rest /= clutPoints[t];
    920             In[t] =  (cmsFloat32Number) (_cmsQuantizeVal(Colorant, clutPoints[t]) / 65535.0);
    921 
    922         }
    923 
    924         if (!Sampler(In, NULL, Cargo))
    925             return FALSE;
    926     }
    927 
    928     return TRUE;
    929 }
    930 
    931 // ********************************************************************************
    932 // Type cmsSigLab2XYZElemType
    933 // ********************************************************************************
    934 
    935 
    936 static
    937 void EvaluateLab2XYZ(const cmsFloat32Number In[],
    938                      cmsFloat32Number Out[],
    939                      const cmsStage *mpe)
    940 {
    941     cmsCIELab Lab;
    942     cmsCIEXYZ XYZ;
    943     const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
    944 
    945     // V4 rules
    946     Lab.L = In[0] * 100.0;
    947     Lab.a = In[1] * 255.0 - 128.0;
    948     Lab.b = In[2] * 255.0 - 128.0;
    949 
    950     cmsLab2XYZ(NULL, &XYZ, &Lab);
    951 
    952     // From XYZ, range 0..19997 to 0..1.0, note that 1.99997 comes from 0xffff
    953     // encoded as 1.15 fixed point, so 1 + (32767.0 / 32768.0)
    954 
    955     Out[0] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.X / XYZadj);
    956     Out[1] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Y / XYZadj);
    957     Out[2] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Z / XYZadj);
    958     return;
    959 
    960     cmsUNUSED_PARAMETER(mpe);
    961 }
    962 
    963 
    964 // No dup or free routines needed, as the structure has no pointers in it.
    965 cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID)
    966 {
    967     return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL);
    968 }
    969 
    970 // ********************************************************************************
    971 
    972 // v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable
    973 // number of gridpoints that would make exact match. However, a prelinearization
    974 // of 258 entries, would map 0xFF00 exactly on entry 257, and this is good to avoid scum dot.
    975 // Almost all what we need but unfortunately, the rest of entries should be scaled by
    976 // (255*257/256) and this is not exact.
    977 
    978 cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
    979 {
    980     cmsStage* mpe;
    981     cmsToneCurve* LabTable[3];
    982     int i, j;
    983 
    984     LabTable[0] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
    985     LabTable[1] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
    986     LabTable[2] = cmsBuildTabulatedToneCurve16(ContextID, 258, NULL);
    987 
    988     for (j=0; j < 3; j++) {
    989 
    990         if (LabTable[j] == NULL) {
    991             cmsFreeToneCurveTriple(LabTable);
    992             return NULL;
    993         }
    994 
    995         // We need to map * (0xffff / 0xff00), thats same as (257 / 256)
    996         // So we can use 258-entry tables to do the trick (i / 257) * (255 * 257) * (257 / 256);
    997         for (i=0; i < 257; i++)  {
    998 
    999             LabTable[j]->Table16[i] = (cmsUInt16Number) ((i * 0xffff + 0x80) >> 8);
   1000         }
   1001 
   1002         LabTable[j] ->Table16[257] = 0xffff;
   1003     }
   1004 
   1005     mpe = cmsStageAllocToneCurves(ContextID, 3, LabTable);
   1006     cmsFreeToneCurveTriple(LabTable);
   1007 
   1008     if (mpe == NULL) return NULL;
   1009     mpe ->Implements = cmsSigLabV2toV4;
   1010     return mpe;
   1011 }
   1012 
   1013 // ********************************************************************************
   1014 
   1015 // Matrix-based conversion, which is more accurate, but slower and cannot properly be saved in devicelink profiles
   1016 cmsStage* _cmsStageAllocLabV2ToV4(cmsContext ContextID)
   1017 {
   1018     static const cmsFloat64Number V2ToV4[] = { 65535.0/65280.0, 0, 0,
   1019                                      0, 65535.0/65280.0, 0,
   1020                                      0, 0, 65535.0/65280.0
   1021                                      };
   1022 
   1023     cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V2ToV4, NULL);
   1024 
   1025     if (mpe == NULL) return mpe;
   1026     mpe ->Implements = cmsSigLabV2toV4;
   1027     return mpe;
   1028 }
   1029 
   1030 
   1031 // Reverse direction
   1032 cmsStage* _cmsStageAllocLabV4ToV2(cmsContext ContextID)
   1033 {
   1034     static const cmsFloat64Number V4ToV2[] = { 65280.0/65535.0, 0, 0,
   1035                                      0, 65280.0/65535.0, 0,
   1036                                      0, 0, 65280.0/65535.0
   1037                                      };
   1038 
   1039      cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, V4ToV2, NULL);
   1040 
   1041     if (mpe == NULL) return mpe;
   1042     mpe ->Implements = cmsSigLabV4toV2;
   1043     return mpe;
   1044 }
   1045 
   1046 
   1047 // To Lab to float. Note that the MPE gives numbers in normal Lab range
   1048 // and we need 0..1.0 range for the formatters
   1049 // L* : 0...100 => 0...1.0  (L* / 100)
   1050 // ab* : -128..+127 to 0..1  ((ab* + 128) / 255)
   1051 
   1052 cmsStage* _cmsStageNormalizeFromLabFloat(cmsContext ContextID)
   1053 {
   1054     static const cmsFloat64Number a1[] = {
   1055         1.0/100.0, 0, 0,
   1056         0, 1.0/255.0, 0,
   1057         0, 0, 1.0/255.0
   1058     };
   1059 
   1060     static const cmsFloat64Number o1[] = {
   1061         0,
   1062         128.0/255.0,
   1063         128.0/255.0
   1064     };
   1065 
   1066     cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, o1);
   1067 
   1068     if (mpe == NULL) return mpe;
   1069     mpe ->Implements = cmsSigLab2FloatPCS;
   1070     return mpe;
   1071 }
   1072 
   1073 // Fom XYZ to floating point PCS
   1074 cmsStage* _cmsStageNormalizeFromXyzFloat(cmsContext ContextID)
   1075 {
   1076 #define n (32768.0/65535.0)
   1077     static const cmsFloat64Number a1[] = {
   1078         n, 0, 0,
   1079         0, n, 0,
   1080         0, 0, n
   1081     };
   1082 #undef n
   1083 
   1084     cmsStage *mpe =  cmsStageAllocMatrix(ContextID, 3, 3, a1, NULL);
   1085 
   1086     if (mpe == NULL) return mpe;
   1087     mpe ->Implements = cmsSigXYZ2FloatPCS;
   1088     return mpe;
   1089 }
   1090 
   1091 cmsStage* _cmsStageNormalizeToLabFloat(cmsContext ContextID)
   1092 {
   1093     static const cmsFloat64Number a1[] = {
   1094         100.0, 0, 0,
   1095         0, 255.0, 0,
   1096         0, 0, 255.0
   1097     };
   1098 
   1099     static const cmsFloat64Number o1[] = {
   1100         0,
   1101         -128.0,
   1102         -128.0
   1103     };
   1104 
   1105     cmsStage *mpe =  cmsStageAllocMatrix(ContextID, 3, 3, a1, o1);
   1106     if (mpe == NULL) return mpe;
   1107     mpe ->Implements = cmsSigFloatPCS2Lab;
   1108     return mpe;
   1109 }
   1110 
   1111 cmsStage* _cmsStageNormalizeToXyzFloat(cmsContext ContextID)
   1112 {
   1113 #define n (65535.0/32768.0)
   1114 
   1115     static const cmsFloat64Number a1[] = {
   1116         n, 0, 0,
   1117         0, n, 0,
   1118         0, 0, n
   1119     };
   1120 #undef n
   1121 
   1122     cmsStage *mpe = cmsStageAllocMatrix(ContextID, 3, 3, a1, NULL);
   1123     if (mpe == NULL) return mpe;
   1124     mpe ->Implements = cmsSigFloatPCS2XYZ;
   1125     return mpe;
   1126 }
   1127 
   1128 // Clips values smaller than zero
   1129 static
   1130 void Clipper(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
   1131 {
   1132        cmsUInt32Number i;
   1133        for (i = 0; i < mpe->InputChannels; i++) {
   1134 
   1135               cmsFloat32Number n = In[i];
   1136               Out[i] = n < 0 ? 0 : n;
   1137        }
   1138 }
   1139 
   1140 cmsStage*  _cmsStageClipNegatives(cmsContext ContextID, int nChannels)
   1141 {
   1142        return _cmsStageAllocPlaceholder(ContextID, cmsSigClipNegativesElemType,
   1143               nChannels, nChannels, Clipper, NULL, NULL, NULL);
   1144 }
   1145 
   1146 // ********************************************************************************
   1147 // Type cmsSigXYZ2LabElemType
   1148 // ********************************************************************************
   1149 
   1150 static
   1151 void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
   1152 {
   1153     cmsCIELab Lab;
   1154     cmsCIEXYZ XYZ;
   1155     const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
   1156 
   1157     // From 0..1.0 to XYZ
   1158 
   1159     XYZ.X = In[0] * XYZadj;
   1160     XYZ.Y = In[1] * XYZadj;
   1161     XYZ.Z = In[2] * XYZadj;
   1162 
   1163     cmsXYZ2Lab(NULL, &Lab, &XYZ);
   1164 
   1165     // From V4 Lab to 0..1.0
   1166 
   1167     Out[0] = (cmsFloat32Number) (Lab.L / 100.0);
   1168     Out[1] = (cmsFloat32Number) ((Lab.a + 128.0) / 255.0);
   1169     Out[2] = (cmsFloat32Number) ((Lab.b + 128.0) / 255.0);
   1170     return;
   1171 
   1172     cmsUNUSED_PARAMETER(mpe);
   1173 }
   1174 
   1175 cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID)
   1176 {
   1177     return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL);
   1178 
   1179 }
   1180 
   1181 // ********************************************************************************
   1182 
   1183 // For v4, S-Shaped curves are placed in a/b axis to increase resolution near gray
   1184 
   1185 cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID)
   1186 {
   1187     cmsToneCurve* LabTable[3];
   1188     cmsFloat64Number Params[1] =  {2.4} ;
   1189 
   1190     LabTable[0] = cmsBuildGamma(ContextID, 1.0);
   1191     LabTable[1] = cmsBuildParametricToneCurve(ContextID, 108, Params);
   1192     LabTable[2] = cmsBuildParametricToneCurve(ContextID, 108, Params);
   1193 
   1194     return cmsStageAllocToneCurves(ContextID, 3, LabTable);
   1195 }
   1196 
   1197 
   1198 // Free a single MPE
   1199 void CMSEXPORT cmsStageFree(cmsStage* mpe)
   1200 {
   1201     if (mpe ->FreePtr)
   1202         mpe ->FreePtr(mpe);
   1203 
   1204     _cmsFree(mpe ->ContextID, mpe);
   1205 }
   1206 
   1207 
   1208 cmsUInt32Number  CMSEXPORT cmsStageInputChannels(const cmsStage* mpe)
   1209 {
   1210     return mpe ->InputChannels;
   1211 }
   1212 
   1213 cmsUInt32Number  CMSEXPORT cmsStageOutputChannels(const cmsStage* mpe)
   1214 {
   1215     return mpe ->OutputChannels;
   1216 }
   1217 
   1218 cmsStageSignature CMSEXPORT cmsStageType(const cmsStage* mpe)
   1219 {
   1220     return mpe -> Type;
   1221 }
   1222 
   1223 void* CMSEXPORT cmsStageData(const cmsStage* mpe)
   1224 {
   1225     return mpe -> Data;
   1226 }
   1227 
   1228 cmsStage*  CMSEXPORT cmsStageNext(const cmsStage* mpe)
   1229 {
   1230     return mpe -> Next;
   1231 }
   1232 
   1233 
   1234 // Duplicates an MPE
   1235 cmsStage* CMSEXPORT cmsStageDup(cmsStage* mpe)
   1236 {
   1237     cmsStage* NewMPE;
   1238 
   1239     if (mpe == NULL) return NULL;
   1240     NewMPE = _cmsStageAllocPlaceholder(mpe ->ContextID,
   1241                                      mpe ->Type,
   1242                                      mpe ->InputChannels,
   1243                                      mpe ->OutputChannels,
   1244                                      mpe ->EvalPtr,
   1245                                      mpe ->DupElemPtr,
   1246                                      mpe ->FreePtr,
   1247                                      NULL);
   1248     if (NewMPE == NULL) return NULL;
   1249 
   1250     NewMPE ->Implements = mpe ->Implements;
   1251 
   1252     if (mpe ->DupElemPtr) {
   1253 
   1254         NewMPE ->Data = mpe ->DupElemPtr(mpe);
   1255 
   1256         if (NewMPE->Data == NULL) {
   1257 
   1258             cmsStageFree(NewMPE);
   1259             return NULL;
   1260         }
   1261 
   1262     } else {
   1263 
   1264         NewMPE ->Data       = NULL;
   1265     }
   1266 
   1267     return NewMPE;
   1268 }
   1269 
   1270 
   1271 // ***********************************************************************************************************
   1272 
   1273 // This function sets up the channel count
   1274 static
   1275 cmsBool BlessLUT(cmsPipeline* lut)
   1276 {
   1277     // We can set the input/ouput channels only if we have elements.
   1278     if (lut ->Elements != NULL) {
   1279 
   1280         cmsStage* prev;
   1281         cmsStage* next;
   1282         cmsStage* First;
   1283         cmsStage* Last;
   1284 
   1285         First  = cmsPipelineGetPtrToFirstStage(lut);
   1286         Last   = cmsPipelineGetPtrToLastStage(lut);
   1287 
   1288         if (First == NULL || Last == NULL) return FALSE;
   1289 
   1290         lut->InputChannels = First->InputChannels;
   1291         lut->OutputChannels = Last->OutputChannels;
   1292 
   1293         // Check chain consistency
   1294         prev = First;
   1295         next = prev->Next;
   1296 
   1297         while (next != NULL)
   1298         {
   1299             if (next->InputChannels != prev->OutputChannels)
   1300                 return FALSE;
   1301 
   1302             next = next->Next;
   1303             prev = prev->Next;
   1304         }
   1305     }
   1306     return TRUE;
   1307 }
   1308 
   1309 
   1310 // Default to evaluate the LUT on 16 bit-basis. Precision is retained.
   1311 static
   1312 void _LUTeval16(register const cmsUInt16Number In[], register cmsUInt16Number Out[],  register const void* D)
   1313 {
   1314     cmsPipeline* lut = (cmsPipeline*) D;
   1315     cmsStage *mpe;
   1316     cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS] = {0.0f};
   1317     int Phase = 0, NextPhase;
   1318 
   1319     From16ToFloat(In, &Storage[Phase][0], lut ->InputChannels);
   1320 
   1321     for (mpe = lut ->Elements;
   1322          mpe != NULL;
   1323          mpe = mpe ->Next) {
   1324 
   1325              NextPhase = Phase ^ 1;
   1326              mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe);
   1327              Phase = NextPhase;
   1328     }
   1329 
   1330 
   1331     FromFloatTo16(&Storage[Phase][0], Out, lut ->OutputChannels);
   1332 }
   1333 
   1334 
   1335 
   1336 // Does evaluate the LUT on cmsFloat32Number-basis.
   1337 static
   1338 void _LUTevalFloat(register const cmsFloat32Number In[], register cmsFloat32Number Out[], const void* D)
   1339 {
   1340     cmsPipeline* lut = (cmsPipeline*) D;
   1341     cmsStage *mpe;
   1342     cmsFloat32Number Storage[2][MAX_STAGE_CHANNELS] = {0.0f};
   1343     int Phase = 0, NextPhase;
   1344 
   1345     memmove(&Storage[Phase][0], In, lut ->InputChannels  * sizeof(cmsFloat32Number));
   1346 
   1347     for (mpe = lut ->Elements;
   1348          mpe != NULL;
   1349          mpe = mpe ->Next) {
   1350 
   1351               NextPhase = Phase ^ 1;
   1352               mpe ->EvalPtr(&Storage[Phase][0], &Storage[NextPhase][0], mpe);
   1353               Phase = NextPhase;
   1354     }
   1355 
   1356     memmove(Out, &Storage[Phase][0], lut ->OutputChannels * sizeof(cmsFloat32Number));
   1357 }
   1358 
   1359 
   1360 
   1361 
   1362 // LUT Creation & Destruction
   1363 
   1364 cmsPipeline* CMSEXPORT cmsPipelineAlloc(cmsContext ContextID, cmsUInt32Number InputChannels, cmsUInt32Number OutputChannels)
   1365 {
   1366        cmsPipeline* NewLUT;
   1367 
   1368        // A value of zero in channels is allowed as placeholder
   1369        if (InputChannels >= cmsMAXCHANNELS ||
   1370            OutputChannels >= cmsMAXCHANNELS) return NULL;
   1371 
   1372        NewLUT = (cmsPipeline*) _cmsMallocZero(ContextID, sizeof(cmsPipeline));
   1373        if (NewLUT == NULL) return NULL;
   1374 
   1375 
   1376        NewLUT -> InputChannels  = InputChannels;
   1377        NewLUT -> OutputChannels = OutputChannels;
   1378 
   1379        NewLUT ->Eval16Fn    = _LUTeval16;
   1380        NewLUT ->EvalFloatFn = _LUTevalFloat;
   1381        NewLUT ->DupDataFn   = NULL;
   1382        NewLUT ->FreeDataFn  = NULL;
   1383        NewLUT ->Data        = NewLUT;
   1384        NewLUT ->ContextID   = ContextID;
   1385 
   1386        if (!BlessLUT(NewLUT))
   1387        {
   1388            _cmsFree(ContextID, NewLUT);
   1389            return NULL;
   1390        }
   1391 
   1392        return NewLUT;
   1393 }
   1394 
   1395 cmsContext CMSEXPORT cmsGetPipelineContextID(const cmsPipeline* lut)
   1396 {
   1397     _cmsAssert(lut != NULL);
   1398     return lut ->ContextID;
   1399 }
   1400 
   1401 cmsUInt32Number CMSEXPORT cmsPipelineInputChannels(const cmsPipeline* lut)
   1402 {
   1403     _cmsAssert(lut != NULL);
   1404     return lut ->InputChannels;
   1405 }
   1406 
   1407 cmsUInt32Number CMSEXPORT cmsPipelineOutputChannels(const cmsPipeline* lut)
   1408 {
   1409     _cmsAssert(lut != NULL);
   1410     return lut ->OutputChannels;
   1411 }
   1412 
   1413 // Free a profile elements LUT
   1414 void CMSEXPORT cmsPipelineFree(cmsPipeline* lut)
   1415 {
   1416     cmsStage *mpe, *Next;
   1417 
   1418     if (lut == NULL) return;
   1419 
   1420     for (mpe = lut ->Elements;
   1421         mpe != NULL;
   1422         mpe = Next) {
   1423 
   1424             Next = mpe ->Next;
   1425             cmsStageFree(mpe);
   1426     }
   1427 
   1428     if (lut ->FreeDataFn) lut ->FreeDataFn(lut ->ContextID, lut ->Data);
   1429 
   1430     _cmsFree(lut ->ContextID, lut);
   1431 }
   1432 
   1433 
   1434 // Default to evaluate the LUT on 16 bit-basis.
   1435 void CMSEXPORT cmsPipelineEval16(const cmsUInt16Number In[], cmsUInt16Number Out[],  const cmsPipeline* lut)
   1436 {
   1437     _cmsAssert(lut != NULL);
   1438     lut ->Eval16Fn(In, Out, lut->Data);
   1439 }
   1440 
   1441 
   1442 // Does evaluate the LUT on cmsFloat32Number-basis.
   1443 void CMSEXPORT cmsPipelineEvalFloat(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsPipeline* lut)
   1444 {
   1445     _cmsAssert(lut != NULL);
   1446     lut ->EvalFloatFn(In, Out, lut);
   1447 }
   1448 
   1449 
   1450 
   1451 // Duplicates a LUT
   1452 cmsPipeline* CMSEXPORT cmsPipelineDup(const cmsPipeline* lut)
   1453 {
   1454     cmsPipeline* NewLUT;
   1455     cmsStage *NewMPE, *Anterior = NULL, *mpe;
   1456     cmsBool  First = TRUE;
   1457 
   1458     if (lut == NULL) return NULL;
   1459 
   1460     NewLUT = cmsPipelineAlloc(lut ->ContextID, lut ->InputChannels, lut ->OutputChannels);
   1461     if (NewLUT == NULL) return NULL;
   1462 
   1463     for (mpe = lut ->Elements;
   1464          mpe != NULL;
   1465          mpe = mpe ->Next) {
   1466 
   1467              NewMPE = cmsStageDup(mpe);
   1468 
   1469              if (NewMPE == NULL) {
   1470                  cmsPipelineFree(NewLUT);
   1471                  return NULL;
   1472              }
   1473 
   1474              if (First) {
   1475                  NewLUT ->Elements = NewMPE;
   1476                  First = FALSE;
   1477              }
   1478              else {
   1479                 if (Anterior != NULL)
   1480                     Anterior ->Next = NewMPE;
   1481              }
   1482 
   1483             Anterior = NewMPE;
   1484     }
   1485 
   1486     NewLUT ->Eval16Fn    = lut ->Eval16Fn;
   1487     NewLUT ->EvalFloatFn = lut ->EvalFloatFn;
   1488     NewLUT ->DupDataFn   = lut ->DupDataFn;
   1489     NewLUT ->FreeDataFn  = lut ->FreeDataFn;
   1490 
   1491     if (NewLUT ->DupDataFn != NULL)
   1492         NewLUT ->Data = NewLUT ->DupDataFn(lut ->ContextID, lut->Data);
   1493 
   1494 
   1495     NewLUT ->SaveAs8Bits    = lut ->SaveAs8Bits;
   1496 
   1497     if (!BlessLUT(NewLUT))
   1498     {
   1499         _cmsFree(lut->ContextID, NewLUT);
   1500         return NULL;
   1501     }
   1502 
   1503     return NewLUT;
   1504 }
   1505 
   1506 
   1507 int CMSEXPORT cmsPipelineInsertStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage* mpe)
   1508 {
   1509     cmsStage* Anterior = NULL, *pt;
   1510 
   1511     if (lut == NULL || mpe == NULL)
   1512         return FALSE;
   1513 
   1514     switch (loc) {
   1515 
   1516         case cmsAT_BEGIN:
   1517             mpe ->Next = lut ->Elements;
   1518             lut ->Elements = mpe;
   1519             break;
   1520 
   1521         case cmsAT_END:
   1522 
   1523             if (lut ->Elements == NULL)
   1524                 lut ->Elements = mpe;
   1525             else {
   1526 
   1527                 for (pt = lut ->Elements;
   1528                      pt != NULL;
   1529                      pt = pt -> Next) Anterior = pt;
   1530 
   1531                 Anterior ->Next = mpe;
   1532                 mpe ->Next = NULL;
   1533             }
   1534             break;
   1535         default:;
   1536             return FALSE;
   1537     }
   1538 
   1539     return BlessLUT(lut);
   1540 }
   1541 
   1542 // Unlink an element and return the pointer to it
   1543 void CMSEXPORT cmsPipelineUnlinkStage(cmsPipeline* lut, cmsStageLoc loc, cmsStage** mpe)
   1544 {
   1545     cmsStage *Anterior, *pt, *Last;
   1546     cmsStage *Unlinked = NULL;
   1547 
   1548 
   1549     // If empty LUT, there is nothing to remove
   1550     if (lut ->Elements == NULL) {
   1551         if (mpe) *mpe = NULL;
   1552         return;
   1553     }
   1554 
   1555     // On depending on the strategy...
   1556     switch (loc) {
   1557 
   1558         case cmsAT_BEGIN:
   1559             {
   1560                 cmsStage* elem = lut ->Elements;
   1561 
   1562                 lut ->Elements = elem -> Next;
   1563                 elem ->Next = NULL;
   1564                 Unlinked = elem;
   1565 
   1566             }
   1567             break;
   1568 
   1569         case cmsAT_END:
   1570             Anterior = Last = NULL;
   1571             for (pt = lut ->Elements;
   1572                 pt != NULL;
   1573                 pt = pt -> Next) {
   1574                     Anterior = Last;
   1575                     Last = pt;
   1576             }
   1577 
   1578             Unlinked = Last;  // Next already points to NULL
   1579 
   1580             // Truncate the chain
   1581             if (Anterior)
   1582                 Anterior ->Next = NULL;
   1583             else
   1584                 lut ->Elements = NULL;
   1585             break;
   1586         default:;
   1587     }
   1588 
   1589     if (mpe)
   1590         *mpe = Unlinked;
   1591     else
   1592         cmsStageFree(Unlinked);
   1593 
   1594     // May fail, but we ignore it
   1595     BlessLUT(lut);
   1596 }
   1597 
   1598 
   1599 // Concatenate two LUT into a new single one
   1600 cmsBool  CMSEXPORT cmsPipelineCat(cmsPipeline* l1, const cmsPipeline* l2)
   1601 {
   1602     cmsStage* mpe;
   1603 
   1604     // If both LUTS does not have elements, we need to inherit
   1605     // the number of channels
   1606     if (l1 ->Elements == NULL && l2 ->Elements == NULL) {
   1607         l1 ->InputChannels  = l2 ->InputChannels;
   1608         l1 ->OutputChannels = l2 ->OutputChannels;
   1609     }
   1610 
   1611     // Cat second
   1612     for (mpe = l2 ->Elements;
   1613          mpe != NULL;
   1614          mpe = mpe ->Next) {
   1615 
   1616             // We have to dup each element
   1617             if (!cmsPipelineInsertStage(l1, cmsAT_END, cmsStageDup(mpe)))
   1618                 return FALSE;
   1619     }
   1620 
   1621     return BlessLUT(l1);
   1622 }
   1623 
   1624 
   1625 cmsBool CMSEXPORT cmsPipelineSetSaveAs8bitsFlag(cmsPipeline* lut, cmsBool On)
   1626 {
   1627     cmsBool Anterior = lut ->SaveAs8Bits;
   1628 
   1629     lut ->SaveAs8Bits = On;
   1630     return Anterior;
   1631 }
   1632 
   1633 
   1634 cmsStage* CMSEXPORT cmsPipelineGetPtrToFirstStage(const cmsPipeline* lut)
   1635 {
   1636     return lut ->Elements;
   1637 }
   1638 
   1639 cmsStage* CMSEXPORT cmsPipelineGetPtrToLastStage(const cmsPipeline* lut)
   1640 {
   1641     cmsStage *mpe, *Anterior = NULL;
   1642 
   1643     for (mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next)
   1644         Anterior = mpe;
   1645 
   1646     return Anterior;
   1647 }
   1648 
   1649 cmsUInt32Number CMSEXPORT cmsPipelineStageCount(const cmsPipeline* lut)
   1650 {
   1651     cmsStage *mpe;
   1652     cmsUInt32Number n;
   1653 
   1654     for (n=0, mpe = lut ->Elements; mpe != NULL; mpe = mpe ->Next)
   1655             n++;
   1656 
   1657     return n;
   1658 }
   1659 
   1660 // This function may be used to set the optional evaluator and a block of private data. If private data is being used, an optional
   1661 // duplicator and free functions should also be specified in order to duplicate the LUT construct. Use NULL to inhibit such functionality.
   1662 void CMSEXPORT _cmsPipelineSetOptimizationParameters(cmsPipeline* Lut,
   1663                                         _cmsOPTeval16Fn Eval16,
   1664                                         void* PrivateData,
   1665                                         _cmsFreeUserDataFn FreePrivateDataFn,
   1666                                         _cmsDupUserDataFn  DupPrivateDataFn)
   1667 {
   1668 
   1669     Lut ->Eval16Fn = Eval16;
   1670     Lut ->DupDataFn = DupPrivateDataFn;
   1671     Lut ->FreeDataFn = FreePrivateDataFn;
   1672     Lut ->Data = PrivateData;
   1673 }
   1674 
   1675 
   1676 // ----------------------------------------------------------- Reverse interpolation
   1677 // Here's how it goes. The derivative Df(x) of the function f is the linear
   1678 // transformation that best approximates f near the point x. It can be represented
   1679 // by a matrix A whose entries are the partial derivatives of the components of f
   1680 // with respect to all the coordinates. This is know as the Jacobian
   1681 //
   1682 // The best linear approximation to f is given by the matrix equation:
   1683 //
   1684 // y-y0 = A (x-x0)
   1685 //
   1686 // So, if x0 is a good "guess" for the zero of f, then solving for the zero of this
   1687 // linear approximation will give a "better guess" for the zero of f. Thus let y=0,
   1688 // and since y0=f(x0) one can solve the above equation for x. This leads to the
   1689 // Newton's method formula:
   1690 //
   1691 // xn+1 = xn - A-1 f(xn)
   1692 //
   1693 // where xn+1 denotes the (n+1)-st guess, obtained from the n-th guess xn in the
   1694 // fashion described above. Iterating this will give better and better approximations
   1695 // if you have a "good enough" initial guess.
   1696 
   1697 
   1698 #define JACOBIAN_EPSILON            0.001f
   1699 #define INVERSION_MAX_ITERATIONS    30
   1700 
   1701 // Increment with reflexion on boundary
   1702 static
   1703 void IncDelta(cmsFloat32Number *Val)
   1704 {
   1705     if (*Val < (1.0 - JACOBIAN_EPSILON))
   1706 
   1707         *Val += JACOBIAN_EPSILON;
   1708 
   1709     else
   1710         *Val -= JACOBIAN_EPSILON;
   1711 
   1712 }
   1713 
   1714 
   1715 
   1716 // Euclidean distance between two vectors of n elements each one
   1717 static
   1718 cmsFloat32Number EuclideanDistance(cmsFloat32Number a[], cmsFloat32Number b[], int n)
   1719 {
   1720     cmsFloat32Number sum = 0;
   1721     int i;
   1722 
   1723     for (i=0; i < n; i++) {
   1724         cmsFloat32Number dif = b[i] - a[i];
   1725         sum +=  dif * dif;
   1726     }
   1727 
   1728     return sqrtf(sum);
   1729 }
   1730 
   1731 
   1732 // Evaluate a LUT in reverse direction. It only searches on 3->3 LUT. Uses Newton method
   1733 //
   1734 // x1 <- x - [J(x)]^-1 * f(x)
   1735 //
   1736 // lut: The LUT on where to do the search
   1737 // Target: LabK, 3 values of Lab plus destination K which is fixed
   1738 // Result: The obtained CMYK
   1739 // Hint:   Location where begin the search
   1740 
   1741 cmsBool CMSEXPORT cmsPipelineEvalReverseFloat(cmsFloat32Number Target[],
   1742                                               cmsFloat32Number Result[],
   1743                                               cmsFloat32Number Hint[],
   1744                                               const cmsPipeline* lut)
   1745 {
   1746     cmsUInt32Number  i, j;
   1747     cmsFloat64Number  error, LastError = 1E20;
   1748     cmsFloat32Number  fx[4], x[4], xd[4], fxd[4];
   1749     cmsVEC3 tmp, tmp2;
   1750     cmsMAT3 Jacobian;
   1751 
   1752     // Only 3->3 and 4->3 are supported
   1753     if (lut ->InputChannels != 3 && lut ->InputChannels != 4) return FALSE;
   1754     if (lut ->OutputChannels != 3) return FALSE;
   1755 
   1756     // Take the hint as starting point if specified
   1757     if (Hint == NULL) {
   1758 
   1759         // Begin at any point, we choose 1/3 of CMY axis
   1760         x[0] = x[1] = x[2] = 0.3f;
   1761     }
   1762     else {
   1763 
   1764         // Only copy 3 channels from hint...
   1765         for (j=0; j < 3; j++)
   1766             x[j] = Hint[j];
   1767     }
   1768 
   1769     // If Lut is 4-dimensions, then grab target[3], which is fixed
   1770     if (lut ->InputChannels == 4) {
   1771         x[3] = Target[3];
   1772     }
   1773     else x[3] = 0; // To keep lint happy
   1774 
   1775 
   1776     // Iterate
   1777     for (i = 0; i < INVERSION_MAX_ITERATIONS; i++) {
   1778 
   1779         // Get beginning fx
   1780         cmsPipelineEvalFloat(x, fx, lut);
   1781 
   1782         // Compute error
   1783         error = EuclideanDistance(fx, Target, 3);
   1784 
   1785         // If not convergent, return last safe value
   1786         if (error >= LastError)
   1787             break;
   1788 
   1789         // Keep latest values
   1790         LastError     = error;
   1791         for (j=0; j < lut ->InputChannels; j++)
   1792                 Result[j] = x[j];
   1793 
   1794         // Found an exact match?
   1795         if (error <= 0)
   1796             break;
   1797 
   1798         // Obtain slope (the Jacobian)
   1799         for (j = 0; j < 3; j++) {
   1800 
   1801             xd[0] = x[0];
   1802             xd[1] = x[1];
   1803             xd[2] = x[2];
   1804             xd[3] = x[3];  // Keep fixed channel
   1805 
   1806             IncDelta(&xd[j]);
   1807 
   1808             cmsPipelineEvalFloat(xd, fxd, lut);
   1809 
   1810             Jacobian.v[0].n[j] = ((fxd[0] - fx[0]) / JACOBIAN_EPSILON);
   1811             Jacobian.v[1].n[j] = ((fxd[1] - fx[1]) / JACOBIAN_EPSILON);
   1812             Jacobian.v[2].n[j] = ((fxd[2] - fx[2]) / JACOBIAN_EPSILON);
   1813         }
   1814 
   1815         // Solve system
   1816         tmp2.n[0] = fx[0] - Target[0];
   1817         tmp2.n[1] = fx[1] - Target[1];
   1818         tmp2.n[2] = fx[2] - Target[2];
   1819 
   1820         if (!_cmsMAT3solve(&tmp, &Jacobian, &tmp2))
   1821             return FALSE;
   1822 
   1823         // Move our guess
   1824         x[0] -= (cmsFloat32Number) tmp.n[0];
   1825         x[1] -= (cmsFloat32Number) tmp.n[1];
   1826         x[2] -= (cmsFloat32Number) tmp.n[2];
   1827 
   1828         // Some clipping....
   1829         for (j=0; j < 3; j++) {
   1830             if (x[j] < 0) x[j] = 0;
   1831             else
   1832                 if (x[j] > 1.0) x[j] = 1.0;
   1833         }
   1834     }
   1835 
   1836     return TRUE;
   1837 }
   1838 
   1839 
   1840