Commit message: Contributed fixes from Oracle

Two minor glitches
CVE: CVE-2016-10165
CWE: CWE-125
Vulnerability description: The Type_MLU_Read function in cmstypes.c in Little CMS (aka lcms2) allows remote attackers to obtain sensitive information or cause a denial of service via an image with a crafted ICC profile, which triggers an out-of-bounds heap read.

Project: Little-CMS

cmsBool OptimizeByComputingLinearization(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
    cmsPipeline* OriginalLut;
    int nGridPoints;
    cmsToneCurve *Trans[cmsMAXCHANNELS], *TransReverse[cmsMAXCHANNELS];
    cmsUInt32Number t, i;
    cmsFloat32Number v, In[cmsMAXCHANNELS], Out[cmsMAXCHANNELS];
    cmsBool lIsSuitable, lIsLinear;
    cmsPipeline* OptimizedLUT = NULL, *LutPlusCurves = NULL;
    cmsStage* OptimizedCLUTmpe;
    cmsColorSpaceSignature ColorSpace, OutputColorSpace;
    cmsStage* OptimizedPrelinMpe;
    cmsStage* mpe;
    cmsToneCurve** OptimizedPrelinCurves;
    _cmsStageCLutData* OptimizedPrelinCLUT;


    // This is a loosy optimization! does not apply in floating-point cases
    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;

    // Only on chunky RGB
    if (T_COLORSPACE(*InputFormat)  != PT_RGB) return FALSE;
    if (T_PLANAR(*InputFormat)) return FALSE;

    if (T_COLORSPACE(*OutputFormat) != PT_RGB) return FALSE;
    if (T_PLANAR(*OutputFormat)) return FALSE;

    // On 16 bits, user has to specify the feature
    if (!_cmsFormatterIs8bit(*InputFormat)) {
        if (!(*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION)) return FALSE;
    }

    OriginalLut = *Lut;

   // Named color pipelines cannot be optimized either
   for (mpe = cmsPipelineGetPtrToFirstStage(OriginalLut);
         mpe != NULL;
         mpe = cmsStageNext(mpe)) {
            if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
    }

    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));
    nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);

    // Empty gamma containers
    memset(Trans, 0, sizeof(Trans));
    memset(TransReverse, 0, sizeof(TransReverse));

    // If the last stage of the original lut are curves, and those curves are
    // degenerated, it is likely the transform is squeezing and clipping
    // the output from previous CLUT. We cannot optimize this case     
    {
        cmsStage* last = cmsPipelineGetPtrToLastStage(OriginalLut);

        if (cmsStageType(last) == cmsSigCurveSetElemType) {

            _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*)cmsStageData(last);
            for (i = 0; i < Data->nCurves; i++) {
                if (IsDegenerated(Data->TheCurves[i]))
                    goto Error;
            }
        }
    }

    for (t = 0; t < OriginalLut ->InputChannels; t++) {
        Trans[t] = cmsBuildTabulatedToneCurve16(OriginalLut ->ContextID, PRELINEARIZATION_POINTS, NULL);
        if (Trans[t] == NULL) goto Error;
    }

    // Populate the curves
    for (i=0; i < PRELINEARIZATION_POINTS; i++) {

        v = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));

        // Feed input with a gray ramp
        for (t=0; t < OriginalLut ->InputChannels; t++)
            In[t] = v;

        // Evaluate the gray value
        cmsPipelineEvalFloat(In, Out, OriginalLut);

        // Store result in curve
        for (t=0; t < OriginalLut ->InputChannels; t++)
            Trans[t] ->Table16[i] = _cmsQuickSaturateWord(Out[t] * 65535.0);
    }

    // Slope-limit the obtained curves
    for (t = 0; t < OriginalLut ->InputChannels; t++)
        SlopeLimiting(Trans[t]);

    // Check for validity
    lIsSuitable = TRUE;
    lIsLinear   = TRUE;
    for (t=0; (lIsSuitable && (t < OriginalLut ->InputChannels)); t++) {

        // Exclude if already linear
        if (!cmsIsToneCurveLinear(Trans[t]))
            lIsLinear = FALSE;

        // Exclude if non-monotonic
        if (!cmsIsToneCurveMonotonic(Trans[t]))
            lIsSuitable = FALSE;

        if (IsDegenerated(Trans[t]))
            lIsSuitable = FALSE;
    }

    // If it is not suitable, just quit
    if (!lIsSuitable) goto Error;

    // Invert curves if possible
    for (t = 0; t < OriginalLut ->InputChannels; t++) {
        TransReverse[t] = cmsReverseToneCurveEx(PRELINEARIZATION_POINTS, Trans[t]);
        if (TransReverse[t] == NULL) goto Error;
    }

    // Now inset the reversed curves at the begin of transform
    LutPlusCurves = cmsPipelineDup(OriginalLut);
    if (LutPlusCurves == NULL) goto Error;

    if (!cmsPipelineInsertStage(LutPlusCurves, cmsAT_BEGIN, cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, TransReverse)))
        goto Error;

    // Create the result LUT
    OptimizedLUT = cmsPipelineAlloc(OriginalLut ->ContextID, OriginalLut ->InputChannels, OriginalLut ->OutputChannels);
    if (OptimizedLUT == NULL) goto Error;

    OptimizedPrelinMpe = cmsStageAllocToneCurves(OriginalLut ->ContextID, OriginalLut ->InputChannels, Trans);

    // Create and insert the curves at the beginning
    if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_BEGIN, OptimizedPrelinMpe))
        goto Error;

    // Allocate the CLUT for result
    OptimizedCLUTmpe = cmsStageAllocCLut16bit(OriginalLut ->ContextID, nGridPoints, OriginalLut ->InputChannels, OriginalLut ->OutputChannels, NULL);

    // Add the CLUT to the destination LUT
    if (!cmsPipelineInsertStage(OptimizedLUT, cmsAT_END, OptimizedCLUTmpe))
        goto Error;

    // Resample the LUT
    if (!cmsStageSampleCLut16bit(OptimizedCLUTmpe, XFormSampler16, (void*) LutPlusCurves, 0)) goto Error;

    // Free resources
    for (t = 0; t < OriginalLut ->InputChannels; t++) {

        if (Trans[t]) cmsFreeToneCurve(Trans[t]);
        if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]);
    }

    cmsPipelineFree(LutPlusCurves);


    OptimizedPrelinCurves = _cmsStageGetPtrToCurveSet(OptimizedPrelinMpe);
    OptimizedPrelinCLUT   = (_cmsStageCLutData*) OptimizedCLUTmpe ->Data;

    // Set the evaluator if 8-bit
    if (_cmsFormatterIs8bit(*InputFormat)) {

        Prelin8Data* p8 = PrelinOpt8alloc(OptimizedLUT ->ContextID,
                                                OptimizedPrelinCLUT ->Params,
                                                OptimizedPrelinCurves);
        if (p8 == NULL) return FALSE;

        _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval8, (void*) p8, Prelin8free, Prelin8dup);

    }
    else
    {
        Prelin16Data* p16 = PrelinOpt16alloc(OptimizedLUT ->ContextID,
            OptimizedPrelinCLUT ->Params,
            3, OptimizedPrelinCurves, 3, NULL);
        if (p16 == NULL) return FALSE;

        _cmsPipelineSetOptimizationParameters(OptimizedLUT, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);

    }

    // Don't fix white on absolute colorimetric
    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
        *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP;

    if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {

        if (!FixWhiteMisalignment(OptimizedLUT, ColorSpace, OutputColorSpace)) {

            return FALSE;
        }
    }

    // And return the obtained LUT

    cmsPipelineFree(OriginalLut);
    *Lut = OptimizedLUT;
    return TRUE;

Error:

    for (t = 0; t < OriginalLut ->InputChannels; t++) {

        if (Trans[t]) cmsFreeToneCurve(Trans[t]);
        if (TransReverse[t]) cmsFreeToneCurve(TransReverse[t]);
    }

    if (LutPlusCurves != NULL) cmsPipelineFree(LutPlusCurves);
    if (OptimizedLUT != NULL) cmsPipelineFree(OptimizedLUT);

    return FALSE;

    cmsUNUSED_PARAMETER(Intent);
}

Project: Little-CMS
File: cmstypes.c

void *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsStage* mpe = NULL;
    cmsUInt16Number InputChans, OutputChans;
    cmsUInt32Number i, BaseOffset;
    cmsToneCurve** GammaTables;

    *nItems = 0;

    // Get actual position as a basis for element offsets
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;

    if (InputChans != OutputChans) return NULL;

    GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*));
    if (GammaTables == NULL) return NULL;

    if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) {

        mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables);
    }
    else {
        mpe = NULL;
    }

    for (i=0; i < InputChans; i++) {
        if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]);
    }

    _cmsFree(self ->ContextID, GammaTables);
    *nItems = (mpe != NULL) ? 1 : 0;
    return mpe;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

void *Type_vcgt_Read(struct _cms_typehandler_struct* self,
                     cmsIOHANDLER* io,
                     cmsUInt32Number* nItems,
                     cmsUInt32Number SizeOfTag)
{
    cmsUInt32Number TagType, n, i;
    cmsToneCurve** Curves;

    *nItems = 0;

    // Read tag type
    if (!_cmsReadUInt32Number(io, &TagType)) return NULL;

    // Allocate space for the array
    Curves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
    if (Curves == NULL) return NULL;

    // There are two possible flavors
    switch (TagType) {

    // Gamma is stored as a table
    case cmsVideoCardGammaTableType:
    {
       cmsUInt16Number nChannels, nElems, nBytes;

       // Check channel count, which should be 3 (we don't support monochrome this time)
       if (!_cmsReadUInt16Number(io, &nChannels)) goto Error;

       if (nChannels != 3) {
           cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported number of channels for VCGT '%d'", nChannels);
           goto Error;
       }

       // Get Table element count and bytes per element
       if (!_cmsReadUInt16Number(io, &nElems)) goto Error;
       if (!_cmsReadUInt16Number(io, &nBytes)) goto Error;

       // Adobe's quirk fixup. Fixing broken profiles...
       if (nElems == 256 && nBytes == 1 && SizeOfTag == 1576)
           nBytes = 2;


       // Populate tone curves
       for (n=0; n < 3; n++) {

           Curves[n] = cmsBuildTabulatedToneCurve16(self ->ContextID, nElems, NULL);
           if (Curves[n] == NULL) goto Error;

           // On depending on byte depth
           switch (nBytes) {

           // One byte, 0..255
           case 1:
               for (i=0; i < nElems; i++) {

                   cmsUInt8Number v;

                      if (!_cmsReadUInt8Number(io, &v)) goto Error;
                      Curves[n] ->Table16[i] = FROM_8_TO_16(v);
               }
               break;

           // One word 0..65535
           case 2:
              if (!_cmsReadUInt16Array(io, nElems, Curves[n]->Table16)) goto Error;
              break;

          // Unsupported
           default:
              cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported bit depth for VCGT '%d'", nBytes * 8);
              goto Error;
           }
       } // For all 3 channels
    }
    break;

   // In this case, gamma is stored as a formula
   case cmsVideoCardGammaFormulaType:
   {
       _cmsVCGTGAMMA Colorant[3];

        // Populate tone curves
       for (n=0; n < 3; n++) {

           double Params[10];

           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error;
           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error;
           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error;

            // Parametric curve type 5 is:
            // Y = (aX + b)^Gamma + e | X >= d
            // Y = cX + f             | X < d

            // vcgt formula is:
            // Y = (Max  Min) * (X ^ Gamma) + Min

            // So, the translation is
            // a = (Max  Min) ^ ( 1 / Gamma)
            // e = Min
            // b=c=d=f=0

           Params[0] = Colorant[n].Gamma;
           Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma));
           Params[2] = 0;
           Params[3] = 0;
           Params[4] = 0;
           Params[5] = Colorant[n].Min;
           Params[6] = 0;

           Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
           if (Curves[n] == NULL) goto Error;
       }
   }
   break;

   // Unsupported
   default:
      cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
      goto Error;
   }

   *nItems = 1;
   return (void*) Curves;

// Regret,  free all resources
Error:

    cmsFreeToneCurveTriple(Curves);
    _cmsFree(self ->ContextID, Curves);
    return NULL;

     cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsMLU* mlu = (cmsMLU*) Ptr;
    cmsUInt32Number size;
    cmsBool  rc;
    char* Text;

    // Get the size of the string. Note there is an extra "\0" at the end
    size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
    if (size == 0) return FALSE;       // Cannot be zero!

    // Create memory
    Text = (char*) _cmsMalloc(self ->ContextID, size);
    if (Text == NULL) return FALSE;

    cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);

    // Write it, including separator
    rc = io ->Write(io, size, Text);

    _cmsFree(self ->ContextID, Text);
    return rc;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS

cmsBool FixWhiteMisalignment(cmsPipeline* Lut, cmsColorSpaceSignature EntryColorSpace, cmsColorSpaceSignature ExitColorSpace)
{
    cmsUInt16Number *WhitePointIn, *WhitePointOut;
    cmsUInt16Number  WhiteIn[cmsMAXCHANNELS], WhiteOut[cmsMAXCHANNELS], ObtainedOut[cmsMAXCHANNELS];
    cmsUInt32Number i, nOuts, nIns;
    cmsStage *PreLin = NULL, *CLUT = NULL, *PostLin = NULL;

    if (!_cmsEndPointsBySpace(EntryColorSpace,
        &WhitePointIn, NULL, &nIns)) return FALSE;

    if (!_cmsEndPointsBySpace(ExitColorSpace,
        &WhitePointOut, NULL, &nOuts)) return FALSE;

    // It needs to be fixed?
    if (Lut ->InputChannels != nIns) return FALSE;
    if (Lut ->OutputChannels != nOuts) return FALSE;

    cmsPipelineEval16(WhitePointIn, ObtainedOut, Lut);

    if (WhitesAreEqual(nOuts, WhitePointOut, ObtainedOut)) return TRUE; // whites already match

    // Check if the LUT comes as Prelin, CLUT or Postlin. We allow all combinations
    if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &PreLin, &CLUT, &PostLin))
        if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCurveSetElemType, cmsSigCLutElemType, &PreLin, &CLUT))
            if (!cmsPipelineCheckAndRetreiveStages(Lut, 2, cmsSigCLutElemType, cmsSigCurveSetElemType, &CLUT, &PostLin))
                if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCLutElemType, &CLUT))
                    return FALSE;

    // We need to interpolate white points of both, pre and post curves
    if (PreLin) {

        cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PreLin);

        for (i=0; i < nIns; i++) {
            WhiteIn[i] = cmsEvalToneCurve16(Curves[i], WhitePointIn[i]);
        }
    }
    else {
        for (i=0; i < nIns; i++)
            WhiteIn[i] = WhitePointIn[i];
    }

    // If any post-linearization, we need to find how is represented white before the curve, do
    // a reverse interpolation in this case.
    if (PostLin) {

        cmsToneCurve** Curves = _cmsStageGetPtrToCurveSet(PostLin);

        for (i=0; i < nOuts; i++) {

            cmsToneCurve* InversePostLin = cmsReverseToneCurve(Curves[i]);
            if (InversePostLin == NULL) {
                WhiteOut[i] = WhitePointOut[i];    

            } else {

                WhiteOut[i] = cmsEvalToneCurve16(InversePostLin, WhitePointOut[i]);
                cmsFreeToneCurve(InversePostLin);
            }
        }
    }
    else {
        for (i=0; i < nOuts; i++)
            WhiteOut[i] = WhitePointOut[i];
    }

    // Ok, proceed with patching. May fail and we don't care if it fails
    PatchLUT(CLUT, WhiteIn, WhiteOut, nOuts, nIns);

    return TRUE;
}

Project: Little-CMS
File: cmstypes.c

void DupTagList(struct _cmsContext_struct* ctx, 
                    const struct _cmsContext_struct* src)
{
   _cmsTagPluginChunkType newHead = { NULL };
   _cmsTagLinkedList*  entry;
   _cmsTagLinkedList*  Anterior = NULL;
   _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin];

   // Walk the list copying all nodes
   for (entry = head->Tag;
       entry != NULL;
       entry = entry ->Next) {

           _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList));

           if (newEntry == NULL) 
               return;

           // We want to keep the linked list order, so this is a little bit tricky
           newEntry -> Next = NULL;
           if (Anterior)
               Anterior -> Next = newEntry;

           Anterior = newEntry;

           if (newHead.Tag == NULL)
               newHead.Tag = newEntry;
   }

   ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType));
}

Project: Little-CMS
File: cmsopt.c

int XFormSampler16(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
{
    cmsPipeline* Lut = (cmsPipeline*) Cargo;
    cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
    cmsUInt32Number i;

    _cmsAssert(Lut -> InputChannels < cmsMAXCHANNELS);
    _cmsAssert(Lut -> OutputChannels < cmsMAXCHANNELS);

    // From 16 bit to floating point
    for (i=0; i < Lut ->InputChannels; i++)
        InFloat[i] = (cmsFloat32Number) (In[i] / 65535.0);

    // Evaluate in floating point
    cmsPipelineEvalFloat(InFloat, OutFloat, Lut);

    // Back to 16 bits representation
    for (i=0; i < Lut ->OutputChannels; i++)
        Out[i] = _cmsQuickSaturateWord(OutFloat[i] * 65535.0);

    // Always succeed
    return TRUE;
}

Project: Little-CMS
File: cmstypes.c

cmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
{
    cmsUInt32Number rv = 1, rc;

    if (a == 0) return 0;
    if (n == 0) return 0;

    for (; b > 0; b--) {

        rv *= a;

        // Check for overflow
        if (rv > UINT_MAX / a) return (cmsUInt32Number) -1;

    }

    rc = rv * n;

    if (rv != rc / n) return (cmsUInt32Number) -1;
    return rc;
}

Project: Little-CMS

void *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt16Number InputChans, OutputChans;
    cmsUInt32Number ElementCount;
    cmsPipeline *NewLUT = NULL;
    cmsUInt32Number BaseOffset;

    // Get actual position as a basis for element offsets
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // Read channels and element count
    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;

    if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) return NULL;
    if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) return NULL;

    // Allocates an empty LUT
    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
    if (NewLUT == NULL) return NULL;

    if (!_cmsReadUInt32Number(io, &ElementCount)) goto Error;    
    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) goto Error;

    // Check channel count
    if (InputChans != NewLUT->InputChannels ||
        OutputChans != NewLUT->OutputChannels) goto Error;

    // Success
    *nItems = 1;
    return NewLUT;

    // Error
Error:    
    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
    *nItems = 0;
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS

void *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
    cmsUInt8Number* Temp = NULL;
    cmsPipeline* NewLUT = NULL;
    cmsUInt32Number nTabSize, i;
    cmsFloat64Number Matrix[3*3];

    *nItems = 0;

    if (!_cmsReadUInt8Number(io, &InputChannels)) goto Error;
    if (!_cmsReadUInt8Number(io, &OutputChannels)) goto Error;
    if (!_cmsReadUInt8Number(io, &CLUTpoints)) goto Error;

     if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least

    // Padding
    if (!_cmsReadUInt8Number(io, NULL)) goto Error;

    // Do some checking
    if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS)  goto Error;
    if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error;

   // Allocates an empty Pipeline
    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
    if (NewLUT == NULL) goto Error;

    // Read the Matrix
    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;


    // Only operates if not identity...
    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {

        if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
            goto Error;
    }

    // Get input tables
    if (!Read8bitTables(self ->ContextID, io,  NewLUT, InputChannels)) goto Error;

    // Get 3D CLUT. Check the overflow....
    nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
    if (nTabSize == (cmsUInt32Number) -1) goto Error;
    if (nTabSize > 0) {

        cmsUInt16Number *PtrW, *T;
       
        PtrW = T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
        if (T  == NULL) goto Error;

        Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize);
        if (Temp == NULL) {
            _cmsFree(self ->ContextID, T);
            goto Error;
        }

        if (io ->Read(io, Temp, nTabSize, 1) != 1) {
            _cmsFree(self ->ContextID, T);
            _cmsFree(self ->ContextID, Temp);
            goto Error;
        }

        for (i = 0; i < nTabSize; i++) {

            *PtrW++ = FROM_8_TO_16(Temp[i]);
        }
        _cmsFree(self ->ContextID, Temp);
        Temp = NULL;

        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
            _cmsFree(self ->ContextID, T);
            goto Error;
        }
        _cmsFree(self ->ContextID, T);
    }


    // Get output tables
    if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;

    *nItems = 1;
    return NewLUT;

Error:
    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool ReadOneElem(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset)
{
    if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE;
    if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE;

    // An offset of zero has special meaning and shal be preserved
    if (e ->Offsets[i] > 0)
        e ->Offsets[i] += BaseOffset;
    return TRUE;
}

Project: Little-CMS
File: cmstypes.c

void _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx, 
                                 const struct _cmsContext_struct* src)
{
    if (src != NULL) {
        
        // Duplicate the LIST
        DupTagTypeList(ctx, src, TagTypePlugin);
    }
    else {
        static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
        ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
    }
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt32Number nTabSize;
    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
    cmsStage* mpe;
    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
    _cmsStageMatrixData* MatMPE = NULL;
    _cmsStageCLutData* clut = NULL;
    int i, InputChannels, OutputChannels, clutPoints;

    // Disassemble the LUT into components.
    mpe = NewLUT -> Elements;
    if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {

        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
        mpe = mpe -> Next;
    }


    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
        mpe = mpe -> Next;
    }

    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
        clut  = (_cmsStageCLutData*) mpe -> Data;
        mpe = mpe ->Next;
    }

    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
        mpe = mpe -> Next;
    }

    // That should be all
    if (mpe != NULL) {
        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
        return FALSE;
    }

    InputChannels  = cmsPipelineInputChannels(NewLUT);
    OutputChannels = cmsPipelineOutputChannels(NewLUT);

    if (clut == NULL)
        clutPoints = 0;
    else
        clutPoints    = clut->Params->nSamples[0];

    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding


    if (MatMPE != NULL) {

        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
    }
    else {

        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
    }


    if (PreMPE != NULL) {
        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
    } else {
            if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
    }

    if (PostMPE != NULL) {
        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
    } else {
        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;

    }

    // The prelinearization table

    if (PreMPE != NULL) {
        if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
    }
    else {
        for (i=0; i < InputChannels; i++) {

            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
        }
    }

    nTabSize = uipow(OutputChannels, clutPoints, InputChannels);
    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
    if (nTabSize > 0) {
        // The 3D CLUT.
        if (clut != NULL) {
            if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE;
        }
    }

    // The postlinearization table
    if (PostMPE != NULL) {
        if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
    }
    else {
        for (i=0; i < OutputChannels; i++) {

            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
        }
    }

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS

void* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt32Number      BaseOffset;
    cmsUInt8Number       inputChan;      // Number of input channels
    cmsUInt8Number       outputChan;     // Number of output channels
    cmsUInt32Number      offsetB;        // Offset to first "B" curve
    cmsUInt32Number      offsetMat;      // Offset to matrix
    cmsUInt32Number      offsetM;        // Offset to first "M" curve
    cmsUInt32Number      offsetC;        // Offset to CLUT
    cmsUInt32Number      offsetA;        // Offset to first "A" curve
    cmsPipeline* NewLUT = NULL;


    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;

    if (!_cmsReadUInt16Number(io, NULL)) return NULL;

    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;

    if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL;
    if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL;

    // Allocates an empty LUT
    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
    if (NewLUT == NULL) return NULL;

    if (offsetA!= 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan)))
            goto Error;
    }

    if (offsetC != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
            goto Error;
    }

    if (offsetM != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
            goto Error;
    }

    if (offsetMat != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
            goto Error;
    }

    if (offsetB != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
            goto Error;
    }

    *nItems = 1;
    return NewLUT;
Error:
    cmsPipelineFree(NewLUT);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsPipeline* Lut = (cmsPipeline*) Ptr;
    int inputChan, outputChan;
    cmsStage *A = NULL, *B = NULL, *M = NULL;
    cmsStage * Matrix = NULL;
    cmsStage * CLUT = NULL;
    cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
    cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;

    // Get the base for all offsets
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    if (Lut ->Elements != NULL)
        if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B))
            if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B))
                if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B))
                    if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType,
                        cmsSigMatrixElemType, cmsSigCurveSetElemType, &A, &CLUT, &M, &Matrix, &B)) {

                            cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutAToB");
                            return FALSE;
                    }

    // Get input, output channels
    inputChan  = cmsPipelineInputChannels(Lut);
    outputChan = cmsPipelineOutputChannels(Lut);

    // Write channel count
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE;
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE;
    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;

    // Keep directory to be filled latter
    DirectoryPos = io ->Tell(io);

    // Write the directory
    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;

    if (A != NULL) {

        offsetA = io ->Tell(io) - BaseOffset;
        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE;
    }

    if (CLUT != NULL) {
        offsetC = io ->Tell(io) - BaseOffset;
        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;

    }
    if (M != NULL) {

        offsetM = io ->Tell(io) - BaseOffset;
        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE;
    }

    if (Matrix != NULL) {
        offsetMat = io ->Tell(io) - BaseOffset;
        if (!WriteMatrix(self, io, Matrix)) return FALSE;
    }

    if (B != NULL) {

        offsetB = io ->Tell(io) - BaseOffset;
        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
    }

    CurrentPos = io ->Tell(io);

    if (!io ->Seek(io, DirectoryPos)) return FALSE;

    if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
    if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
    if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
    if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
    if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;

    if (!io ->Seek(io, CurrentPos)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

cmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos)
{
    cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
    _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos);
    _cmsTagTypeLinkedList *pt;

    // Calling the function with NULL as plug-in would unregister the plug in.
    if (Data == NULL) {

        // There is no need to set free the memory, as pool is destroyed as a whole.
        ctx ->TagTypes = NULL;
        return TRUE;
    }

    // Registering happens in plug-in memory pool.
    pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
    if (pt == NULL) return FALSE;

    pt ->Handler   = Plugin ->Handler;
    pt ->Next      = ctx ->TagTypes;

    ctx ->TagTypes = pt;
     
    return TRUE;
}

Project: Little-CMS

void *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt32Number Count;
    cmsToneCurve* NewGamma;
    
    *nItems = 0;
    if (!_cmsReadUInt32Number(io, &Count)) return NULL;

    switch (Count) {

           case 0:   // Linear.
               {
                   cmsFloat64Number SingleGamma = 1.0;

                   NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
                   if (!NewGamma) return NULL;
                   *nItems = 1;
                   return NewGamma;
               }
              
           case 1:  // Specified as the exponent of gamma function
               {
                   cmsUInt16Number SingleGammaFixed;
                   cmsFloat64Number SingleGamma;

                   if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL;
                   SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed);

                   *nItems = 1;
                   return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
               }

           default:  // Curve

               if (Count > 0x7FFF)
                   return NULL; // This is to prevent bad guys for doing bad things

               NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
               if (!NewGamma) return NULL;

               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) {
                   cmsFreeToneCurve(NewGamma);
                   return NULL;
               }

               *nItems = 1;
               return NewGamma;
    }

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS

cmsBool _cmsOptimizePipeline(cmsContext ContextID,
                             cmsPipeline**    PtrLut,
                             int              Intent,
                             cmsUInt32Number* InputFormat,
                             cmsUInt32Number* OutputFormat,
                             cmsUInt32Number* dwFlags)
{
    _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
    _cmsOptimizationCollection* Opts;
    cmsBool AnySuccess = FALSE;

    // A CLUT is being asked, so force this specific optimization
    if (*dwFlags & cmsFLAGS_FORCE_CLUT) {

        PreOptimize(*PtrLut);
        return OptimizeByResampling(PtrLut, Intent, InputFormat, OutputFormat, dwFlags);
    }

    // Anything to optimize?
    if ((*PtrLut) ->Elements == NULL) {
        _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
        return TRUE;
    }

    // Try to get rid of identities and trivial conversions.
    AnySuccess = PreOptimize(*PtrLut);

    // After removal do we end with an identity?
    if ((*PtrLut) ->Elements == NULL) {
        _cmsPipelineSetOptimizationParameters(*PtrLut, FastIdentity16, (void*) *PtrLut, NULL, NULL);
        return TRUE;
    }

    // Do not optimize, keep all precision
    if (*dwFlags & cmsFLAGS_NOOPTIMIZE)
        return FALSE;

    // Try plug-in optimizations 
    for (Opts = ctx->OptimizationCollection;
         Opts != NULL;
         Opts = Opts ->Next) {

            // If one schema succeeded, we are done
            if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) {

                return TRUE;    // Optimized!
            }
    }

   // Try built-in optimizations 
    for (Opts = DefaultOptimization;
         Opts != NULL;
         Opts = Opts ->Next) {

            if (Opts ->OptimizePtr(PtrLut, Intent, InputFormat, OutputFormat, dwFlags)) {

                return TRUE;  
            }
    }

    // Only simple optimizations succeeded
    return AnySuccess;
}

Project: Little-CMS

cmsBool IsDegenerated(const cmsToneCurve* g)
{
    int i, Zeros = 0, Poles = 0;
    int nEntries = g ->nEntries;

    for (i=0; i < nEntries; i++) {

        if (g ->Table16[i] == 0x0000) Zeros++;
        if (g ->Table16[i] == 0xffff) Poles++;
    }

    if (Zeros == 1 && Poles == 1) return FALSE;  // For linear tables
    if (Zeros > (nEntries / 20)) return TRUE;  // Degenerated, many zeros
    if (Poles > (nEntries / 20)) return TRUE;  // Degenerated, many poles

    return FALSE;
}

Project: Little-CMS

cmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
    int i, nColors;

    nColors = cmsNamedColorCount(NamedColorList);

    if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;

    for (i=0; i < nColors; i++) {

        char root[33];
        cmsUInt16Number PCS[3];

        memset(root, 0, sizeof(root));

        if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
        root[32] = 0;

        if (!io ->Write(io, 32, root)) return FALSE;
        if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
    }

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS

cmsBool SetMatShaper(cmsPipeline* Dest, cmsToneCurve* Curve1[3], cmsMAT3* Mat, cmsVEC3* Off, cmsToneCurve* Curve2[3], cmsUInt32Number* OutputFormat)
{
    MatShaper8Data* p;
    int i, j;
    cmsBool Is8Bits = _cmsFormatterIs8bit(*OutputFormat);

    // Allocate a big chuck of memory to store precomputed tables
    p = (MatShaper8Data*) _cmsMalloc(Dest ->ContextID, sizeof(MatShaper8Data));
    if (p == NULL) return FALSE;

    p -> ContextID = Dest -> ContextID;

    // Precompute tables
    FillFirstShaper(p ->Shaper1R, Curve1[0]);
    FillFirstShaper(p ->Shaper1G, Curve1[1]);
    FillFirstShaper(p ->Shaper1B, Curve1[2]);

    FillSecondShaper(p ->Shaper2R, Curve2[0], Is8Bits);
    FillSecondShaper(p ->Shaper2G, Curve2[1], Is8Bits);
    FillSecondShaper(p ->Shaper2B, Curve2[2], Is8Bits);

    // Convert matrix to nFixed14. Note that those values may take more than 16 bits 
    for (i=0; i < 3; i++) {
        for (j=0; j < 3; j++) {
            p ->Mat[i][j] = DOUBLE_TO_1FIXED14(Mat->v[i].n[j]);
        }
    }

    for (i=0; i < 3; i++) {

        if (Off == NULL) {
            p ->Off[i] = 0;
        }
        else {
            p ->Off[i] = DOUBLE_TO_1FIXED14(Off->n[i]);
        }
    }

    // Mark as optimized for faster formatter
    if (Is8Bits)
        *OutputFormat |= OPTIMIZED_SH(1);

    // Fill function pointers
    _cmsPipelineSetOptimizationParameters(Dest, MatShaperEval16, (void*) p, FreeMatShaper, DupMatShaper);
    return TRUE;
}

Project: Little-CMS
File: cmstypes.c

cmsBool ReadOffsetArray(cmsIOHANDLER* io,  _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset)
{
    cmsUInt32Number i;

    // Read column arrays
    for (i=0; i < Count; i++) {

        if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE;
        if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE;

        if (Length > 16) {

            if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE;

        }

        if (Length > 24) {

            if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE;
        }
    }
    return TRUE;
}

Project: Little-CMS

void* CurvesDup(cmsContext ContextID, const void* ptr)
{
    Curves16Data* Data = (Curves16Data*)_cmsDupMem(ContextID, ptr, sizeof(Curves16Data));
    int i;

    if (Data == NULL) return NULL;

    Data->Curves = (cmsUInt16Number**) _cmsDupMem(ContextID, Data->Curves, Data->nCurves * sizeof(cmsUInt16Number*));

    for (i=0; i < Data -> nCurves; i++) {
        Data->Curves[i] = (cmsUInt16Number*) _cmsDupMem(ContextID, Data->Curves[i], Data->nElements * sizeof(cmsUInt16Number));
    }

    return (void*) Data;
}

Project: Little-CMS
File: cmstypes.c

cmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu)
{
    cmsUInt32Number nItems = 0;

    // A way to get null MLUCs
    if (e -> Offsets[i] == 0 || e ->Sizes[i] == 0) {

        *mlu = NULL;
        return TRUE;
    }

    if (!io -> Seek(io, e -> Offsets[i])) return FALSE;

    *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]);
    return *mlu != NULL;
}

Project: Little-CMS

cmsBool  isFloatMatrixIdentity(const cmsMAT3* a)
{
       cmsMAT3 Identity;
       int i, j;

       _cmsMAT3identity(&Identity);

       for (i = 0; i < 3; i++)
              for (j = 0; j < 3; j++)
                     if (!CloseEnoughFloat(a->v[i].n[j], Identity.v[i].n[j])) return FALSE;

       return TRUE;
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
{
    cmsUInt32Number i, j;
    cmsCurveSegment* Segments = g ->Segments;
    cmsUInt32Number nSegments = g ->nSegments;

    if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error;
    if (!_cmsWriteUInt32Number(io, 0)) goto Error;
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error;
    if (!_cmsWriteUInt16Number(io, 0)) goto Error;

    // Write the break-points
    for (i=0; i < nSegments - 1; i++) {
        if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error;
    }

    // Write the segments
    for (i=0; i < g ->nSegments; i++) {

        cmsCurveSegment* ActualSeg = Segments + i;

        if (ActualSeg -> Type == 0) {

            // This is a sampled curve
            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error;
            if (!_cmsWriteUInt32Number(io, 0)) goto Error;
            if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error;

            for (j=0; j < g ->Segments[i].nGridPoints; j++) {
                if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error;
            }

        }
        else {
            int Type;
            cmsUInt32Number ParamsByType[] = { 4, 5, 5 };

            // This is a formula-based
            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigFormulaCurveSeg)) goto Error;
            if (!_cmsWriteUInt32Number(io, 0)) goto Error;

            // We only allow 1, 2 and 3 as types
            Type = ActualSeg ->Type - 6;
            if (Type > 2 || Type < 0) goto Error;

            if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Type)) goto Error;
            if (!_cmsWriteUInt16Number(io, 0)) goto Error;

            for (j=0; j < ParamsByType[Type]; j++) {
                if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) ActualSeg ->Params[j])) goto Error;
            }
        }

        // It seems there is no need to align. Code is here, and for safety commented out
        // if (!_cmsWriteAlignment(io)) goto Error;
    }

    return TRUE;

Error:
    return FALSE;
}

Project: Little-CMS
File: cmstypes.c

void *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsFloat64Number*  array_double;
    cmsUInt32Number v;
    cmsUInt32Number i, n;

    *nItems = 0;
    n = SizeOfTag / sizeof(cmsUInt32Number);
    array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number));
    if (array_double == NULL) return NULL;

    for (i=0; i < n; i++) {

        if (!_cmsReadUInt32Number(io, &v)) {
            _cmsFree(self ->ContextID, (void*) array_double);
            return NULL;
        }

        // Convert to cmsFloat64Number
        array_double[i] =  (cmsFloat64Number) (v / 65536.0);
    }

    *nItems = n;
    return (void*) array_double;
}

Project: Little-CMS
File: cmstypes.c

cmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsToneCurve** Curves =  (cmsToneCurve**) Ptr;
    cmsUInt32Number i, j;

    if (cmsGetToneCurveParametricType(Curves[0]) == 5 &&
        cmsGetToneCurveParametricType(Curves[1]) == 5 &&
        cmsGetToneCurveParametricType(Curves[2]) == 5) {

            if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE;

            // Save parameters
            for (i=0; i < 3; i++) {

                _cmsVCGTGAMMA v;

                v.Gamma = Curves[i] ->Segments[0].Params[0];
                v.Min   = Curves[i] ->Segments[0].Params[5];
                v.Max   = pow(Curves[i] ->Segments[0].Params[1], v.Gamma) + v.Min;

                if (!_cmsWrite15Fixed16Number(io, v.Gamma)) return FALSE;
                if (!_cmsWrite15Fixed16Number(io, v.Min)) return FALSE;
                if (!_cmsWrite15Fixed16Number(io, v.Max)) return FALSE;
            }
    }

    else {

        // Always store as a table of 256 words
        if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE;
        if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
        if (!_cmsWriteUInt16Number(io, 256)) return FALSE;
        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;

        for (i=0; i < 3; i++) {
            for (j=0; j < 256; j++) {

                cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0));
                cmsUInt16Number  n = _cmsQuickSaturateWord(v * 65535.0);

                if (!_cmsWriteUInt16Number(io, n)) return FALSE;
            }
        }
    }

    return TRUE;

    cmsUNUSED_PARAMETER(self);
    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsSEQ* Seq = (cmsSEQ*) Ptr;
    cmsUInt32Number BaseOffset;

    // Keep the base offset
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // This is the table count
    if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE;

    // This is the position table and content
    if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS

Prelin16Data* PrelinOpt16alloc(cmsContext ContextID,
                               const cmsInterpParams* ColorMap,
                               int nInputs, cmsToneCurve** In,
                               int nOutputs, cmsToneCurve** Out )
{
    int i;
    Prelin16Data* p16 = (Prelin16Data*)_cmsMallocZero(ContextID, sizeof(Prelin16Data));
    if (p16 == NULL) return NULL;

    p16 ->nInputs = nInputs;
    p16 -> nOutputs = nOutputs;


    for (i=0; i < nInputs; i++) {

        if (In == NULL) {
            p16 -> ParamsCurveIn16[i] = NULL;
            p16 -> EvalCurveIn16[i] = Eval16nop1D;

        }
        else {
            p16 -> ParamsCurveIn16[i] = In[i] ->InterpParams;
            p16 -> EvalCurveIn16[i] = p16 ->ParamsCurveIn16[i]->Interpolation.Lerp16;
        }
    }

    p16 ->CLUTparams = ColorMap;
    p16 ->EvalCLUT   = ColorMap ->Interpolation.Lerp16;


    p16 -> EvalCurveOut16 = (_cmsInterpFn16*) _cmsCalloc(ContextID, nOutputs, sizeof(_cmsInterpFn16));
    p16 -> ParamsCurveOut16 = (cmsInterpParams**) _cmsCalloc(ContextID, nOutputs, sizeof(cmsInterpParams* ));

    for (i=0; i < nOutputs; i++) {

        if (Out == NULL) {
            p16 ->ParamsCurveOut16[i] = NULL;
            p16 -> EvalCurveOut16[i] = Eval16nop1D;
        }
        else {

            p16 ->ParamsCurveOut16[i] = Out[i] ->InterpParams;
            p16 -> EvalCurveOut16[i] = p16 ->ParamsCurveOut16[i]->Interpolation.Lerp16;
        }
    }

    return p16;
}

Project: Little-CMS

void* Prelin16dup(cmsContext ContextID, const void* ptr)
{
    Prelin16Data* p16 = (Prelin16Data*) ptr;
    Prelin16Data* Duped = (Prelin16Data*) _cmsDupMem(ContextID, p16, sizeof(Prelin16Data));

    if (Duped == NULL) return NULL;

    Duped->EvalCurveOut16 = (_cmsInterpFn16*) _cmsDupMem(ContextID, p16->EvalCurveOut16, p16->nOutputs * sizeof(_cmsInterpFn16));
    Duped->ParamsCurveOut16 = (cmsInterpParams**)_cmsDupMem(ContextID, p16->ParamsCurveOut16, p16->nOutputs * sizeof(cmsInterpParams*));

    return Duped;
}

Project: Little-CMS

cmsBool  _cmsRegisterOptimizationPlugin(cmsContext ContextID, cmsPluginBase* Data)
{
    cmsPluginOptimization* Plugin = (cmsPluginOptimization*) Data;
    _cmsOptimizationPluginChunkType* ctx = ( _cmsOptimizationPluginChunkType*) _cmsContextGetClientChunk(ContextID, OptimizationPlugin);
    _cmsOptimizationCollection* fl;

    if (Data == NULL) {

        ctx->OptimizationCollection = NULL;
        return TRUE;
    }

    // Optimizer callback is required
    if (Plugin ->OptimizePtr == NULL) return FALSE;

    fl = (_cmsOptimizationCollection*) _cmsPluginMalloc(ContextID, sizeof(_cmsOptimizationCollection));
    if (fl == NULL) return FALSE;

    // Copy the parameters
    fl ->OptimizePtr = Plugin ->OptimizePtr;

    // Keep linked list
    fl ->Next = ctx->OptimizationCollection;

    // Set the head
    ctx ->OptimizationCollection = fl;

    // All is ok
    return TRUE;
}

Project: Little-CMS

void *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt32Number i, Count;
    cmsNAMEDCOLORLIST* List;
    char Name[34];
    cmsUInt16Number PCS[3];


    if (!_cmsReadUInt32Number(io, &Count)) return NULL;

    if (Count > cmsMAXCHANNELS) {
        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many colorants '%d'", Count);
        return NULL;
    }

    List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
    for (i=0; i < Count; i++) {

        if (io ->Read(io, Name, 32, 1) != 1) goto Error;
        Name[32] = 0;

        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;

        if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error;

    }

    *nItems = 1;
    return List;

Error:
    *nItems = 0;
    cmsFreeNamedColorList(List);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt32Number j, nTabSize;
    cmsUInt8Number  val;
    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
    cmsStage* mpe;
    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
    _cmsStageMatrixData* MatMPE = NULL;
    _cmsStageCLutData* clut = NULL;
    int clutPoints;

    // Disassemble the LUT into components.
    mpe = NewLUT -> Elements;
    if (mpe ->Type == cmsSigMatrixElemType) {

        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
        mpe = mpe -> Next;
    }

    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
        mpe = mpe -> Next;
    }

    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
        clut  = (_cmsStageCLutData*) mpe -> Data;
        mpe = mpe ->Next;
    }

    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
        mpe = mpe -> Next;
    }

    // That should be all
    if (mpe != NULL) {
        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
        return FALSE;
    }


    if (clut == NULL)
        clutPoints = 0;
    else
        clutPoints    = clut->Params->nSamples[0];

    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding


    if (MatMPE != NULL) {

        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;

    }
    else {

        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
    }

    // The prelinearization table
    if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;

    nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
    if (nTabSize > 0) {

        // The 3D CLUT.
        if (clut != NULL) {

            for (j=0; j < nTabSize; j++) {

                val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]);
                if (!_cmsWriteUInt8Number(io, val)) return FALSE;
            }
        }
    }

    // The postlinearization table
    if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

cmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
{
    cmsFloat64Number dMat[3*3];
    cmsFloat64Number dOff[3];
    cmsStage* Mat;

    // Go to address
    if (!io -> Seek(io, Offset)) return NULL;

    // Read the Matrix
    if (!_cmsRead15Fixed16Number(io, &dMat[0])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[1])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[2])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[3])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[4])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[5])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[6])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[7])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dMat[8])) return NULL;

    if (!_cmsRead15Fixed16Number(io, &dOff[0])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dOff[1])) return NULL;
    if (!_cmsRead15Fixed16Number(io, &dOff[2])) return NULL;

    Mat = cmsStageAllocMatrix(self ->ContextID, 3, 3, dMat, dOff);

     return Mat;
}

Project: Little-CMS

void *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsStage* mpe;
    cmsUInt16Number   InputChans, OutputChans;
    cmsUInt32Number   nElems, i;
    cmsFloat64Number* Matrix;
    cmsFloat64Number* Offsets;

    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;


    // Input and output chans may be ANY (up to 0xffff), 
    // but we choose to limit to 16 channels for now
    if (InputChans >= cmsMAXCHANNELS) return NULL;
    if (OutputChans >= cmsMAXCHANNELS) return NULL;

    nElems = InputChans * OutputChans;

    Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number));
    if (Matrix == NULL) return NULL;

    Offsets = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, OutputChans, sizeof(cmsFloat64Number));
    if (Offsets == NULL) {

        _cmsFree(self ->ContextID, Matrix);
        return NULL;
    }

    for (i=0; i < nElems; i++) {

        cmsFloat32Number v;

        if (!_cmsReadFloat32Number(io, &v)) {
            _cmsFree(self ->ContextID, Matrix);
            _cmsFree(self ->ContextID, Offsets);
            return NULL;
        }
        Matrix[i] = v;
    }


    for (i=0; i < OutputChans; i++) {

        cmsFloat32Number v;

        if (!_cmsReadFloat32Number(io, &v)) {
            _cmsFree(self ->ContextID, Matrix);
            _cmsFree(self ->ContextID, Offsets);
            return NULL;
        }
        Offsets[i] = v;
    }


    mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets);
    _cmsFree(self ->ContextID, Matrix);
    _cmsFree(self ->ContextID, Offsets);

    *nItems = 1;

    return mpe;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmsopt.c

void SlopeLimiting(cmsToneCurve* g)
{
    int BeginVal, EndVal;
    int AtBegin = (int) floor((cmsFloat64Number) g ->nEntries * 0.02 + 0.5);   // Cutoff at 2%
    int AtEnd   = g ->nEntries - AtBegin - 1;                                  // And 98%
    cmsFloat64Number Val, Slope, beta;
    int i;

    if (cmsIsToneCurveDescending(g)) {
        BeginVal = 0xffff; EndVal = 0;
    }
    else {
        BeginVal = 0; EndVal = 0xffff;
    }

    // Compute slope and offset for begin of curve
    Val   = g ->Table16[AtBegin];
    Slope = (Val - BeginVal) / AtBegin;
    beta  = Val - Slope * AtBegin;

    for (i=0; i < AtBegin; i++)
        g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta);

    // Compute slope and offset for the end
    Val   = g ->Table16[AtEnd];
    Slope = (EndVal - Val) / AtBegin;   // AtBegin holds the X interval, which is same in both cases
    beta  = Val - Slope * AtEnd;

    for (i = AtEnd; i < (int) g ->nEntries; i++)
        g ->Table16[i] = _cmsQuickSaturateWord(i * Slope + beta);
}

Project: Little-CMS

void *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{

    cmsUInt32Number      vendorFlag;     // Bottom 16 bits for ICC use
    cmsUInt32Number      count;          // Count of named colors
    cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
    char                 prefix[32];     // Prefix for each color name
    char                 suffix[32];     // Suffix for each color name
    cmsNAMEDCOLORLIST*   v;
    cmsUInt32Number      i;


    *nItems = 0;
    if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL;
    if (!_cmsReadUInt32Number(io, &count)) return NULL;
    if (!_cmsReadUInt32Number(io, &nDeviceCoords)) return NULL;

    if (io -> Read(io, prefix, 32, 1) != 1) return NULL;
    if (io -> Read(io, suffix, 32, 1) != 1) return NULL;

    prefix[31] = suffix[31] = 0;

    v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix);
    if (v == NULL) {
        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many named colors '%d'", count);
        return NULL;
    }

    if (nDeviceCoords > cmsMAXCHANNELS) {
        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
        goto Error;
    }
    for (i=0; i < count; i++) {

        cmsUInt16Number PCS[3];
        cmsUInt16Number Colorant[cmsMAXCHANNELS];
        char Root[33];

        memset(Colorant, 0, sizeof(Colorant));
        if (io -> Read(io, Root, 32, 1) != 1) goto Error;
        Root[32] = 0;  // To prevent exploits

        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
        if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;

        if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
    }

    *nItems = 1;
    return (void*) v ;

Error:
    cmsFreeNamedColorList(v);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS

cmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
    int inputChan, outputChan;
    cmsUInt32Number ElemCount;
    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
    cmsStageSignature ElementSig;
    cmsPipeline* Lut = (cmsPipeline*) Ptr;
    cmsStage* Elem = Lut ->Elements;
    cmsTagTypeHandler* TypeHandler;
    _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);

    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    inputChan  = cmsPipelineInputChannels(Lut);
    outputChan = cmsPipelineOutputChannels(Lut);
    ElemCount  = cmsPipelineStageCount(Lut);

    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
    if (ElementOffsets == NULL) goto Error;

    ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
    if (ElementSizes == NULL) goto Error;

    // Write the head
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) inputChan)) goto Error;
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) outputChan)) goto Error;
    if (!_cmsWriteUInt32Number(io, (cmsUInt16Number) ElemCount)) goto Error;

    DirectoryPos = io ->Tell(io);

    // Write a fake directory to be filled latter on
    for (i=0; i < ElemCount; i++) {
        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
    }

    // Write each single tag. Keep track of the size as well.
    for (i=0; i < ElemCount; i++) {

        ElementOffsets[i] = io ->Tell(io) - BaseOffset;

        ElementSig = Elem ->Type;

        TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes);
        if (TypeHandler == NULL)  {

                char String[5];

                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);

                 // An unknown element was found.
                 cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String);
                 goto Error;
        }

        if (!_cmsWriteUInt32Number(io, ElementSig)) goto Error;
        if (!_cmsWriteUInt32Number(io, 0)) goto Error;
        Before = io ->Tell(io);
        if (!TypeHandler ->WritePtr(self, io, Elem, 1)) goto Error;
        if (!_cmsWriteAlignment(io)) goto Error;

        ElementSizes[i] = io ->Tell(io) - Before;

        Elem = Elem ->Next;
    }

    // Write the directory
    CurrentPos = io ->Tell(io);

    if (!io ->Seek(io, DirectoryPos)) goto Error;

    for (i=0; i < ElemCount; i++) {
        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
    }

    if (!io ->Seek(io, CurrentPos)) goto Error;

    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
    return TRUE;

Error:
    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
    return FALSE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

void DupTagTypeList(struct _cmsContext_struct* ctx, 
                    const struct _cmsContext_struct* src, 
                    int loc)
{
   _cmsTagTypePluginChunkType newHead = { NULL };
   _cmsTagTypeLinkedList*  entry;
   _cmsTagTypeLinkedList*  Anterior = NULL;
   _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];

   // Walk the list copying all nodes
   for (entry = head->TagTypes;
       entry != NULL;
       entry = entry ->Next) {

           _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList));

           if (newEntry == NULL) 
               return;

           // We want to keep the linked list order, so this is a little bit tricky
           newEntry -> Next = NULL;
           if (Anterior)
               Anterior -> Next = newEntry;

           Anterior = newEntry;

           if (newHead.TagTypes == NULL)
               newHead.TagTypes = newEntry;
   }

   ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType));
}

Project: Little-CMS

cmsBool CloseEnoughFloat(cmsFloat64Number a, cmsFloat64Number b)
{
       return fabs(b - a) < 0.00001f;
}

Project: Little-CMS
File: cmstypes.c

void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    char* Text = NULL;
    cmsMLU* mlu = NULL;
    cmsUInt32Number  AsciiCount;
    cmsUInt32Number  i, UnicodeCode, UnicodeCount;
    cmsUInt16Number  ScriptCodeCode, Dummy;
    cmsUInt8Number   ScriptCodeCount;

    *nItems = 0;

    //  One dword should be there
    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;

    // Read len of ASCII
    if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    // Check for size
    if (SizeOfTag < AsciiCount) return NULL;

    // All seems Ok, allocate the container
    mlu = cmsMLUalloc(self ->ContextID, 1);
    if (mlu == NULL) return NULL;

    // As many memory as size of tag
    Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1);
    if (Text == NULL) goto Error;

    // Read it
    if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error;
    SizeOfTag -= AsciiCount;

    // Make sure there is a terminator
    Text[AsciiCount] = 0;

    // Set the MLU entry. From here we can be tolerant to wrong types
    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
    _cmsFree(self ->ContextID, (void*) Text);
    Text = NULL;

    // Skip Unicode code
    if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done;
    if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done;
    if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
    SizeOfTag -= 2* sizeof(cmsUInt32Number);

    if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;

    for (i=0; i < UnicodeCount; i++) {
        if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done;
    }
    SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);

    // Skip ScriptCode code if present. Some buggy profiles does have less
    // data that stricttly required. We need to skip it as this type may come
    // embedded in other types.

    if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {

        if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done;
        if (!_cmsReadUInt8Number(io,  &ScriptCodeCount)) goto Done;

        // Skip rest of tag
        for (i=0; i < 67; i++) {
            if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error;
        }
    }

Done:

    *nItems = 1;
    return mlu;

Error:
    if (Text) _cmsFree(self ->ContextID, (void*) Text);
    if (mlu) cmsMLUfree(mlu);
    return NULL;
}

Project: Little-CMS

cmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels)
{
    cmsUInt8Number  gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension.
    cmsUInt32Number GridPoints[cmsMAXCHANNELS], i;
    cmsUInt8Number  Precision;
    cmsStage* CLUT;
    _cmsStageCLutData* Data;

    if (!io -> Seek(io, Offset)) return NULL;
    if (io -> Read(io, gridPoints8, cmsMAXCHANNELS, 1) != 1) return NULL;


    for (i=0; i < cmsMAXCHANNELS; i++) {

        if (gridPoints8[i] == 1) return NULL; // Impossible value, 0 for no CLUT and then 2 at least
        GridPoints[i] = gridPoints8[i];
    }

    if (!_cmsReadUInt8Number(io, &Precision)) return NULL;

    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
    if (!_cmsReadUInt8Number(io, NULL)) return NULL;

    CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL);
    if (CLUT == NULL) return NULL;

    Data = (_cmsStageCLutData*) CLUT ->Data;

    // Precision can be 1 or 2 bytes
    if (Precision == 1) {

        cmsUInt8Number  v;

        for (i=0; i < Data ->nEntries; i++) {

            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) {
                cmsStageFree(CLUT);
                return NULL;
            }
            Data ->Tab.T[i] = FROM_8_TO_16(v);
        }

    }
    else
        if (Precision == 2) {

            if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) {
                cmsStageFree(CLUT);
                return NULL;
            }
        }
        else {
            cmsStageFree(CLUT);
            cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
            return NULL;
        }

        return CLUT;
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteSeqID(struct _cms_typehandler_struct* self,
                                             cmsIOHANDLER* io,
                                             void* Cargo,
                                             cmsUInt32Number n,
                                             cmsUInt32Number SizeOfTag)
{
    cmsSEQ* Seq = (cmsSEQ*) Cargo;

    if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE;

    // Store here the MLU
    if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables)
{
    int j;
    cmsUInt32Number i;
    cmsUInt8Number val;

    for (i=0; i < n; i++) {

        if (Tables) {

            // Usual case of identity curves
            if ((Tables ->TheCurves[i]->nEntries == 2) && 
                (Tables->TheCurves[i]->Table16[0] == 0) && 
                (Tables->TheCurves[i]->Table16[1] == 65535)) {

                    for (j=0; j < 256; j++) {
                        if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE;
                    }
            }
            else 
                if (Tables ->TheCurves[i]->nEntries != 256) {
                    cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
                    return FALSE;                
                }
                else
                    for (j=0; j < 256; j++) {

                        val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);

                        if (!_cmsWriteUInt8Number(io, val)) return FALSE;
                    }
        }
    }
    return TRUE;
}

Project: Little-CMS

void FillFirstShaper(cmsS1Fixed14Number* Table, cmsToneCurve* Curve)
{
    int i;
    cmsFloat32Number R, y;

    for (i=0; i < 256; i++) {

        R   = (cmsFloat32Number) (i / 255.0);
        y   = cmsEvalToneCurveFloat(Curve, R);

        if (y < 131072.0)
            Table[i] = DOUBLE_TO_1FIXED14(y);
        else
            Table[i] = 0x7fffffff;
    }
}

Project: Little-CMS

void *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsMLU* mlu;
    cmsUInt32Number Count, RecLen, NumOfWchar;
    cmsUInt32Number SizeOfHeader;
    cmsUInt32Number  Len, Offset;
    cmsUInt32Number  i;
    wchar_t*         Block;
    cmsUInt32Number  BeginOfThisString, EndOfThisString, LargestPosition;

    *nItems = 0;
    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
    if (!_cmsReadUInt32Number(io, &RecLen)) return NULL;

    if (RecLen != 12) {

        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "multiLocalizedUnicodeType of len != 12 is not supported.");
        return NULL;
    }

    mlu = cmsMLUalloc(self ->ContextID, Count);
    if (mlu == NULL) return NULL;

    mlu ->UsedEntries = Count;

    SizeOfHeader = 12 * Count + sizeof(_cmsTagBase);
    LargestPosition = 0;

    for (i=0; i < Count; i++) {

        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error;
        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country))  goto Error;

        // Now deal with Len and offset.
        if (!_cmsReadUInt32Number(io, &Len)) goto Error;
        if (!_cmsReadUInt32Number(io, &Offset)) goto Error;

        // Check for overflow
        if (Offset < (SizeOfHeader + 8)) goto Error;        
        if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;

        // True begin of the string
        BeginOfThisString = Offset - SizeOfHeader - 8;

        // Ajust to wchar_t elements
        mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
        mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);

        // To guess maximum size, add offset + len
        EndOfThisString = BeginOfThisString + Len;
        if (EndOfThisString > LargestPosition)
            LargestPosition = EndOfThisString;
    }

    // Now read the remaining of tag and fill all strings. Subtract the directory
    SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
    if (SizeOfTag == 0)
    {
        Block = NULL;
        NumOfWchar = 0;

    }
    else
    {
        Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);
        if (Block == NULL) goto Error;
        NumOfWchar = SizeOfTag / sizeof(wchar_t);
        if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error;
    }

    mlu ->MemPool  = Block;
    mlu ->PoolSize = SizeOfTag;
    mlu ->PoolUsed = SizeOfTag;

    *nItems = 1;
    return (void*) mlu;

Error:
    if (mlu) cmsMLUfree(mlu);
    return NULL;
}

Project: Little-CMS

cmsBool OptimizeMatrixShaper(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
       cmsStage* Curve1, *Curve2;
       cmsStage* Matrix1, *Matrix2;
       cmsMAT3 res;
       cmsBool IdentityMat;
       cmsPipeline* Dest, *Src;
       cmsFloat64Number* Offset;

       // Only works on RGB to RGB
       if (T_CHANNELS(*InputFormat) != 3 || T_CHANNELS(*OutputFormat) != 3) return FALSE;

       // Only works on 8 bit input
       if (!_cmsFormatterIs8bit(*InputFormat)) return FALSE;

       // Seems suitable, proceed
       Src = *Lut;

       // Check for:
       // 
       //    shaper-matrix-matrix-shaper 
       //    shaper-matrix-shaper
       // 
       // Both of those constructs are possible (first because abs. colorimetric). 
       // additionally, In the first case, the input matrix offset should be zero.

       IdentityMat = FALSE;
       if (cmsPipelineCheckAndRetreiveStages(Src, 4,
              cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
              &Curve1, &Matrix1, &Matrix2, &Curve2)) {

              // Get both matrices
              _cmsStageMatrixData* Data1 = (_cmsStageMatrixData*)cmsStageData(Matrix1);
              _cmsStageMatrixData* Data2 = (_cmsStageMatrixData*)cmsStageData(Matrix2);

              // Input offset should be zero
              if (Data1->Offset != NULL) return FALSE;

              // Multiply both matrices to get the result
              _cmsMAT3per(&res, (cmsMAT3*)Data2->Double, (cmsMAT3*)Data1->Double);

              // Only 2nd matrix has offset, or it is zero 
              Offset = Data2->Offset;

              // Now the result is in res + Data2 -> Offset. Maybe is a plain identity?
              if (_cmsMAT3isIdentity(&res) && Offset == NULL) {

                     // We can get rid of full matrix
                     IdentityMat = TRUE;
              }

       }
       else {

              if (cmsPipelineCheckAndRetreiveStages(Src, 3,
                     cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
                     &Curve1, &Matrix1, &Curve2)) {

                     _cmsStageMatrixData* Data = (_cmsStageMatrixData*)cmsStageData(Matrix1);

                     // Copy the matrix to our result
                     memcpy(&res, Data->Double, sizeof(res));

                     // Preserve the Odffset (may be NULL as a zero offset)
                     Offset = Data->Offset;

                     if (_cmsMAT3isIdentity(&res) && Offset == NULL) {

                            // We can get rid of full matrix
                            IdentityMat = TRUE;
                     }
              }
              else
                     return FALSE; // Not optimizeable this time

       }

      // Allocate an empty LUT
    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
    if (!Dest) return FALSE;

    // Assamble the new LUT
    if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageDup(Curve1)))
        goto Error;

    if (!IdentityMat) {

           if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageAllocMatrix(Dest->ContextID, 3, 3, (const cmsFloat64Number*)&res, Offset)))
                  goto Error;
    }

    if (!cmsPipelineInsertStage(Dest, cmsAT_END, cmsStageDup(Curve2)))
        goto Error;

    // If identity on matrix, we can further optimize the curves, so call the join curves routine
    if (IdentityMat) {

        OptimizeByJoiningCurves(&Dest, Intent, InputFormat, OutputFormat, dwFlags);
    }
    else {
        _cmsStageToneCurvesData* mpeC1 = (_cmsStageToneCurvesData*) cmsStageData(Curve1);
        _cmsStageToneCurvesData* mpeC2 = (_cmsStageToneCurvesData*) cmsStageData(Curve2);

        // In this particular optimization, cach does not help as it takes more time to deal with
        // the cach that with the pixel handling
        *dwFlags |= cmsFLAGS_NOCACHE;

        // Setup the optimizarion routines
        SetMatShaper(Dest, mpeC1 ->TheCurves, &res, (cmsVEC3*) Offset, mpeC2->TheCurves, OutputFormat);
    }

    cmsPipelineFree(Src);
    *Lut = Dest;
    return TRUE;
Error:
    // Leave Src unchanged
    cmsPipelineFree(Dest);
    return FALSE;
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
{
    int i;
    cmsToneCurve* Tables[cmsMAXCHANNELS];

    // Maybe an empty table? (this is a lcms extension)
    if (nEntries <= 0) return TRUE;

    // Check for malicious profiles
    if (nEntries < 2) return FALSE;
    if (nChannels > cmsMAXCHANNELS) return FALSE;

    // Init table to zero
    memset(Tables, 0, sizeof(Tables));

    for (i=0; i < nChannels; i++) {

        Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, nEntries, NULL);
        if (Tables[i] == NULL) goto Error;

        if (!_cmsReadUInt16Array(io, nEntries, Tables[i]->Table16)) goto Error;
    }


    // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
    if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
        goto Error;

    for (i=0; i < nChannels; i++)
        cmsFreeToneCurve(Tables[i]);

    return TRUE;

Error:
    for (i=0; i < nChannels; i++) {
        if (Tables[i]) cmsFreeToneCurve(Tables[i]);
    }

    return FALSE;
}

Project: Little-CMS
File: cmstypes.c

void *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt8Number* ColorantOrder;
    cmsUInt32Number Count;

    *nItems = 0;
    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
    if (Count > cmsMAXCHANNELS) return NULL;

    ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
    if (ColorantOrder == NULL) return NULL;

    // We use FF as end marker
    memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number));

    if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) {

        _cmsFree(self ->ContextID, (void*) ColorantOrder);
        return NULL;
    }

    *nItems = 1;
    return (void*) ColorantOrder;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS

void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsStage* mpe = NULL;
    cmsUInt16Number InputChans, OutputChans;
    cmsUInt8Number Dimensions8[16];
    cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
    _cmsStageCLutData* clut;

    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;

    if (InputChans == 0) goto Error;
    if (OutputChans == 0) goto Error;

    if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
        goto Error;

    // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
    nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;

    for (i = 0; i < nMaxGrids; i++) {
        if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
        GridPoints[i] = (cmsUInt32Number)Dimensions8[i];
    }
    
    // Allocate the true CLUT
    mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
    if (mpe == NULL) goto Error;

    // Read and sanitize the data
    clut = (_cmsStageCLutData*) mpe ->Data;
    for (i=0; i < clut ->nEntries; i++) {

        if (!_cmsReadFloat32Number(io, &clut->Tab.TFloat[i])) goto Error;       
    }

    *nItems = 1;
    return mpe;

Error:
    *nItems = 0;
    if (mpe != NULL) cmsStageFree(mpe);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS

void* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt8Number       inputChan;      // Number of input channels
    cmsUInt8Number       outputChan;     // Number of output channels
    cmsUInt32Number      BaseOffset;     // Actual position in file
    cmsUInt32Number      offsetB;        // Offset to first "B" curve
    cmsUInt32Number      offsetMat;      // Offset to matrix
    cmsUInt32Number      offsetM;        // Offset to first "M" curve
    cmsUInt32Number      offsetC;        // Offset to CLUT
    cmsUInt32Number      offsetA;        // Offset to first "A" curve
    cmsPipeline* NewLUT = NULL;


    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;

    if (inputChan == 0 || inputChan >= cmsMAXCHANNELS) return NULL;
    if (outputChan == 0 || outputChan >= cmsMAXCHANNELS) return NULL;

    // Padding
    if (!_cmsReadUInt16Number(io, NULL)) return NULL;

    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;

    // Allocates an empty LUT
    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
    if (NewLUT == NULL) return NULL;

    if (offsetB != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan)))
            goto Error;
    }

    if (offsetMat != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
            goto Error;
    }

    if (offsetM != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
            goto Error;
    }

    if (offsetC != 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
            goto Error;
    }

    if (offsetA!= 0) {
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
            goto Error;
    }

    *nItems = 1;
    return NewLUT;
Error:
    cmsPipelineFree(NewLUT);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUcrBg* Value = (cmsUcrBg*) Ptr;
    cmsUInt32Number TextSize;
    char* Text;

    // First curve is Under color removal
    if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE;
    if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE;

    // Then black generation
    if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE;
    if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE;

    // Now comes the text. The length is specified by the tag size
    TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
    Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
    if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;

    if (!io ->Write(io, TextSize, Text)) return FALSE;
    _cmsFree(self ->ContextID, Text);

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

cmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
                    cmsIOHANDLER* io,
                    void* Cargo,
                    cmsUInt32Number n,
                    cmsUInt32Number SizeOfTag)
{
    cmsStageSignature ElementSig;
    cmsTagTypeHandler* TypeHandler;
    cmsUInt32Number nItems;
    cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
    _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);


    // Take signature and channels for each element.
    if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE;

    // The reserved placeholder
    if (!_cmsReadUInt32Number(io, NULL)) return FALSE;

    // Read diverse MPE types
    TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes);
    if (TypeHandler == NULL)  {

        char String[5];

        _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);

        // An unknown element was found.
        cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
        return FALSE;
    }

    // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
    // Read the MPE. No size is given
    if (TypeHandler ->ReadPtr != NULL) {

        // This is a real element which should be read and processed
        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
            return FALSE;
    }

    return TRUE;

    cmsUNUSED_PARAMETER(SizeOfTag);
    cmsUNUSED_PARAMETER(n);
}

Project: Little-CMS
File: cmstypes.c

cmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
{
    // Empty values
    memset(a, 0, sizeof(_cmsDICarray));

    // On depending on record size, create column arrays
    if (!AllocElem(ContextID, &a ->Name, Count)) goto Error;
    if (!AllocElem(ContextID, &a ->Value, Count)) goto Error;

    if (Length > 16) {
        if (!AllocElem(ContextID, &a -> DisplayName, Count)) goto Error;

    }
    if (Length > 24) {
        if (!AllocElem(ContextID, &a ->DisplayValue, Count)) goto Error;
    }
    return TRUE;

Error:
    FreeArray(a);
    return FALSE;
}

Project: Little-CMS
File: cmstypes.c

void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
   cmsHANDLE hDict;
   cmsUInt32Number i, Count, Length;
   cmsUInt32Number BaseOffset;
   _cmsDICarray a;
   wchar_t *NameWCS = NULL, *ValueWCS = NULL;
   cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
   cmsBool rc;

    *nItems = 0;

    // Get actual position as a basis for element offsets
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // Get name-value record count
    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    // Get rec length
    if (!_cmsReadUInt32Number(io, &Length)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    // Check for valid lengths
    if (Length != 16 && Length != 24 && Length != 32) {
         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown record length in dictionary '%d'", Length);
         return NULL;
    }

    // Creates an empty dictionary
    hDict = cmsDictAlloc(self -> ContextID);
    if (hDict == NULL) return NULL;

    // On depending on record size, create column arrays
    if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error;

    // Read column arrays
    if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error;

    // Seek to each element and read it
    for (i=0; i < Count; i++) {

        if (!ReadOneWChar(io, &a.Name, i, &NameWCS)) goto Error;
        if (!ReadOneWChar(io, &a.Value, i, &ValueWCS)) goto Error;

        if (Length > 16) {
            if (!ReadOneMLUC(self, io, &a.DisplayName, i, &DisplayNameMLU)) goto Error;
        }

        if (Length > 24) {
            if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
        }

        if (NameWCS == NULL || ValueWCS == NULL) {
        
            cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value");        
            rc = FALSE;
        }
        else {

            rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
        }

        if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
        if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
        if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
        if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);

        if (!rc) goto Error;
    }

   FreeArray(&a);
   *nItems = 1;
   return (void*) hDict;

Error:
   FreeArray(&a);
   cmsDictFree(hDict);
   return NULL;
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number  Precision, cmsStage* mpe)
{
    cmsUInt8Number  gridPoints[cmsMAXCHANNELS]; // Number of grid points in each dimension.
    cmsUInt32Number i;
    _cmsStageCLutData* CLUT = ( _cmsStageCLutData*) mpe -> Data;

    if (CLUT ->HasFloatValues) {
         cmsSignalError(self ->ContextID, cmsERROR_NOT_SUITABLE, "Cannot save floating point data, CLUT are 8 or 16 bit only");
         return FALSE;
    }

    memset(gridPoints, 0, sizeof(gridPoints));
    for (i=0; i < (cmsUInt32Number) CLUT ->Params ->nInputs; i++)
        gridPoints[i] = (cmsUInt8Number) CLUT ->Params ->nSamples[i];

    if (!io -> Write(io, cmsMAXCHANNELS*sizeof(cmsUInt8Number), gridPoints)) return FALSE;

    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) Precision)) return FALSE;
    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;

    // Precision can be 1 or 2 bytes
    if (Precision == 1) {

        for (i=0; i < CLUT->nEntries; i++) {

            if (!_cmsWriteUInt8Number(io, FROM_16_TO_8(CLUT->Tab.T[i]))) return FALSE;
        }
    }
    else
        if (Precision == 2) {

            if (!_cmsWriteUInt16Array(io, CLUT->nEntries, CLUT ->Tab.T)) return FALSE;
        }
        else {
             cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
            return FALSE;
        }

        if (!_cmsWriteAlignment(io)) return FALSE;

        return TRUE;
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt8Number Dimensions8[16];  // 16 because the spec says 16 and not max number of channels
    cmsUInt32Number i;
    cmsStage* mpe = (cmsStage*) Ptr;
    _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;

    // Check for maximum number of channels supported by lcms
    if (mpe -> InputChannels > MAX_INPUT_DIMENSIONS) return FALSE;

    // Only floats are supported in MPE
    if (clut ->HasFloatValues == FALSE) return FALSE;

    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;

    memset(Dimensions8, 0, sizeof(Dimensions8));

    for (i=0; i < mpe ->InputChannels; i++)
        Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];

    if (!io ->Write(io, 16, Dimensions8)) return FALSE;

    for (i=0; i < clut ->nEntries; i++) {

        if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
    }

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsToneCurve* Curve = (cmsToneCurve*) Ptr;

    if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) {

            // Single gamma, preserve number
            cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]);

            if (!_cmsWriteUInt32Number(io, 1)) return FALSE;
            if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE;
            return TRUE;

    }

    if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE;
    return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16);

    cmsUNUSED_PARAMETER(nItems);
    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS

cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsMLU* mlu = (cmsMLU*) Ptr;
    char *Text = NULL;
    wchar_t *Wide = NULL;
    cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
    cmsBool  rc = FALSE;
    char Filler[68];

    // Used below for writing zeroes
    memset(Filler, 0, sizeof(Filler));

    // Get the len of string
    len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);

    // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data
    //(see clause 4.1 for the definition of aligned). Because the Unicode language
    // code and Unicode count immediately follow the ASCII description, their
    // alignment is not correct if the ASCII count is not a multiple of four. The
    // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
    // writing software must be written carefully in order to handle these alignment
    // problems.
    //
    // The above last sentence suggest to handle alignment issues in the
    // parser. The provided example (Table 69 on Page 60) makes this clear. 
    // The padding only in the ASCII count is not sufficient for a aligned tag
    // size, with the same text size in ASCII and Unicode.

    // Null strings
    if (len <= 0) {

        Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
        Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
    }
    else {
        // Create independent buffers
        Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
        if (Text == NULL) goto Error;

        Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
        if (Wide == NULL) goto Error;

        // Get both representations.
        cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
        cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
    }

    // Tell the real text len including the null terminator and padding
    len_text = (cmsUInt32Number) strlen(Text) + 1;
    // Compute an total tag size requirement
    len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67);
    len_aligned = _cmsALIGNLONG(len_tag_requirement);

  // * cmsUInt32Number       count;          * Description length
  // * cmsInt8Number         desc[count]     * NULL terminated ascii string
  // * cmsUInt32Number       ucLangCode;     * UniCode language code
  // * cmsUInt32Number       ucCount;        * UniCode description length
  // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
  // * cmsUInt16Number       scCode;         * ScriptCode code
  // * cmsUInt8Number        scCount;        * ScriptCode count
  // * cmsInt8Number         scDesc[67];     * ScriptCode Description

    if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
    if (!io ->Write(io, len_text, Text)) goto Error;

    if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // ucLanguageCode

    if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
    // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
    if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error;

    // ScriptCode Code & count (unused)
    if (!_cmsWriteUInt16Number(io, 0)) goto Error;
    if (!_cmsWriteUInt8Number(io, 0)) goto Error;

    if (!io ->Write(io, 67, Filler)) goto Error;

    // possibly add pad at the end of tag
    if(len_aligned - len_tag_requirement > 0)
      if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;

    rc = TRUE;

Error:
    if (Text) _cmsFree(self ->ContextID, Text);
    if (Wide) _cmsFree(self ->ContextID, Wide);

    return rc;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset)
{
    cmsUInt32Number Before = io ->Tell(io);
    cmsUInt32Number n;

    e ->Offsets[i] = Before - BaseOffset;

    if (wcstr == NULL) {
        e ->Sizes[i] = 0;
        e ->Offsets[i] = 0;
        return TRUE;
    }

    n = mywcslen(wcstr);
    if (!_cmsWriteWCharArray(io,  n, wcstr)) return FALSE;

    e ->Sizes[i] = io ->Tell(io) - Before;
    return TRUE;
}

Project: Little-CMS

void *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
    cmsPipeline* NewLUT = NULL;
    cmsUInt32Number nTabSize;
    cmsFloat64Number Matrix[3*3];
    cmsUInt16Number InputEntries, OutputEntries;

    *nItems = 0;

    if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL;
    if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL;
    if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL;   // 255 maximum

    // Padding
    if (!_cmsReadUInt8Number(io, NULL)) return NULL;

    // Do some checking
    if (InputChannels == 0 || InputChannels > cmsMAXCHANNELS)  goto Error;
    if (OutputChannels == 0 || OutputChannels > cmsMAXCHANNELS) goto Error;

    // Allocates an empty LUT
    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
    if (NewLUT == NULL) goto Error;

    // Read the Matrix
    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;


    // Only operates on 3 channels
    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {

        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
            goto Error;
    }

    if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error;
    if (!_cmsReadUInt16Number(io, &OutputEntries)) goto Error;

    if (InputEntries > 0x7FFF || OutputEntries > 0x7FFF) goto Error;
    if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least

    // Get input tables
    if (!Read16bitTables(self ->ContextID, io,  NewLUT, InputChannels, InputEntries)) goto Error;

    // Get 3D CLUT
    nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
    if (nTabSize == (cmsUInt32Number) -1) goto Error;
    if (nTabSize > 0) {

        cmsUInt16Number *T;

        T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
        if (T  == NULL) goto Error;

        if (!_cmsReadUInt16Array(io, nTabSize, T)) {
            _cmsFree(self ->ContextID, T);
            goto Error;
        }

        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
            _cmsFree(self ->ContextID, T);
            goto Error;
        }
        _cmsFree(self ->ContextID, T);
    }


    // Get output tables
    if (!Read16bitTables(self ->ContextID, io,  NewLUT, OutputChannels, OutputEntries)) goto Error;

    *nItems = 1;
    return NewLUT;

Error:
    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt8Number*  ColorantOrder = (cmsUInt8Number*) Ptr;
    cmsUInt32Number i, sz, Count;

    // Get the length
    for (Count=i=0; i < cmsMAXCHANNELS; i++) {
        if (ColorantOrder[i] != 0xFF) Count++;
    }

    if (!_cmsWriteUInt32Number(io, Count)) return FALSE;

    sz = Count * sizeof(cmsUInt8Number);
    if (!io -> Write(io, sz, ColorantOrder)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS
File: cmsopt.c

void MatShaperEval16(register const cmsUInt16Number In[],
                     register cmsUInt16Number Out[],
                     register const void* D)
{
    MatShaper8Data* p = (MatShaper8Data*) D;
    cmsS1Fixed14Number l1, l2, l3, r, g, b;
    cmsUInt32Number ri, gi, bi;

    // In this case (and only in this case!) we can use this simplification since
    // In[] is assured to come from a 8 bit number. (a << 8 | a)
    ri = In[0] & 0xFF;
    gi = In[1] & 0xFF;
    bi = In[2] & 0xFF;

    // Across first shaper, which also converts to 1.14 fixed point
    r = p->Shaper1R[ri];
    g = p->Shaper1G[gi];
    b = p->Shaper1B[bi];

    // Evaluate the matrix in 1.14 fixed point
    l1 =  (p->Mat[0][0] * r + p->Mat[0][1] * g + p->Mat[0][2] * b + p->Off[0] + 0x2000) >> 14;
    l2 =  (p->Mat[1][0] * r + p->Mat[1][1] * g + p->Mat[1][2] * b + p->Off[1] + 0x2000) >> 14;
    l3 =  (p->Mat[2][0] * r + p->Mat[2][1] * g + p->Mat[2][2] * b + p->Off[2] + 0x2000) >> 14;

    // Now we have to clip to 0..1.0 range
    ri = (l1 < 0) ? 0 : ((l1 > 16384) ? 16384 : l1);
    gi = (l2 < 0) ? 0 : ((l2 > 16384) ? 16384 : l2);
    bi = (l3 < 0) ? 0 : ((l3 > 16384) ? 16384 : l3);

    // And across second shaper,
    Out[0] = p->Shaper2R[ri];
    Out[1] = p->Shaper2G[gi];
    Out[2] = p->Shaper2B[bi];

}

Project: Little-CMS

cmsBool _MultiplyMatrix(cmsPipeline* Lut)
{
       cmsStage** pt1;
       cmsStage** pt2;
       cmsStage*  chain;
       cmsBool AnyOpt = FALSE;

       pt1 = &Lut->Elements;
       if (*pt1 == NULL) return AnyOpt;

       while (*pt1 != NULL) {

              pt2 = &((*pt1)->Next);
              if (*pt2 == NULL) return AnyOpt;

              if ((*pt1)->Implements == cmsSigMatrixElemType && (*pt2)->Implements == cmsSigMatrixElemType) {

                     // Get both matrices
                     _cmsStageMatrixData* m1 = (_cmsStageMatrixData*) cmsStageData(*pt1);
                     _cmsStageMatrixData* m2 = (_cmsStageMatrixData*) cmsStageData(*pt2);
                     cmsMAT3 res;
                     
                     // Input offset and output offset should be zero to use this optimization
                     if (m1->Offset != NULL || m2 ->Offset != NULL || 
                            cmsStageInputChannels(*pt1) != 3 || cmsStageOutputChannels(*pt1) != 3 ||                            
                            cmsStageInputChannels(*pt2) != 3 || cmsStageOutputChannels(*pt2) != 3)
                            return FALSE;

                     // Multiply both matrices to get the result
                     _cmsMAT3per(&res, (cmsMAT3*)m2->Double, (cmsMAT3*)m1->Double);

                     // Get the next in chain after the matrices
                     chain = (*pt2)->Next;

                     // Remove both matrices
                     _RemoveElement(pt2);
                     _RemoveElement(pt1);

                     // Now what if the result is a plain identity?                     
                     if (!isFloatMatrixIdentity(&res)) {

                            // We can not get rid of full matrix                            
                            cmsStage* Multmat = cmsStageAllocMatrix(Lut->ContextID, 3, 3, (const cmsFloat64Number*) &res, NULL);
                            if (Multmat == NULL) return FALSE;  // Should never happen

                            // Recover the chain
                            Multmat->Next = chain;
                            *pt1 = Multmat;
                     }

                     AnyOpt = TRUE;
              }
              else
                     pt1 = &((*pt1)->Next);
       }

       return AnyOpt;
}

Project: Little-CMS
File: cmstypes.c

void *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
    cmsUInt32Number CountUcr, CountBg;
    char* ASCIIString;

    *nItems = 0;
    if (n == NULL) return NULL;

    // First curve is Under color removal
    if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
    if (n ->Ucr == NULL) return NULL;

    if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
    SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);

    // Second curve is Black generation
    if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
    if (n ->Bg == NULL) return NULL;
    if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
    if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL;
    SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
    if (SizeOfTag == UINT_MAX) return NULL;

    // Now comes the text. The length is specified by the tag size
    n ->Desc = cmsMLUalloc(self ->ContextID, 1);
    if (n ->Desc == NULL) return NULL;

    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
    if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
    ASCIIString[SizeOfTag] = 0;
    cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
    _cmsFree(self ->ContextID, ASCIIString);

    *nItems = 1;
    return (void*) n;
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsMLU* mlu =(cmsMLU*) Ptr;
    cmsUInt32Number HeaderSize;
    cmsUInt32Number  Len, Offset;
    cmsUInt32Number i;

    if (Ptr == NULL) {

          // Empty placeholder
          if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
          if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
          return TRUE;
    }

    if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
    if (!_cmsWriteUInt32Number(io, 12)) return FALSE;

    HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);

    for (i=0; i < mlu ->UsedEntries; i++) {

        Len    =  mlu ->Entries[i].Len;
        Offset =  mlu ->Entries[i].StrW;

        Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);
        Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8;

        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE;
        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country))  return FALSE;
        if (!_cmsWriteUInt32Number(io, Len)) return FALSE;
        if (!_cmsWriteUInt32Number(io, Offset)) return FALSE;
    }

    if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*)  mlu ->MemPool)) return FALSE;

    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS

cmsBool OptimizeByJoiningCurves(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
    cmsToneCurve** GammaTables = NULL;
    cmsFloat32Number InFloat[cmsMAXCHANNELS], OutFloat[cmsMAXCHANNELS];
    cmsUInt32Number i, j;
    cmsPipeline* Src = *Lut;
    cmsPipeline* Dest = NULL;
    cmsStage* mpe;
    cmsStage* ObtainedCurves = NULL;


    // This is a loosy optimization! does not apply in floating-point cases
    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;

    //  Only curves in this LUT?
    for (mpe = cmsPipelineGetPtrToFirstStage(Src);
         mpe != NULL;
         mpe = cmsStageNext(mpe)) {
            if (cmsStageType(mpe) != cmsSigCurveSetElemType) return FALSE;
    }

    // Allocate an empty LUT
    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
    if (Dest == NULL) return FALSE;

    // Create target curves
    GammaTables = (cmsToneCurve**) _cmsCalloc(Src ->ContextID, Src ->InputChannels, sizeof(cmsToneCurve*));
    if (GammaTables == NULL) goto Error;

    for (i=0; i < Src ->InputChannels; i++) {
        GammaTables[i] = cmsBuildTabulatedToneCurve16(Src ->ContextID, PRELINEARIZATION_POINTS, NULL);
        if (GammaTables[i] == NULL) goto Error;
    }

    // Compute 16 bit result by using floating point
    for (i=0; i < PRELINEARIZATION_POINTS; i++) {

        for (j=0; j < Src ->InputChannels; j++)
            InFloat[j] = (cmsFloat32Number) ((cmsFloat64Number) i / (PRELINEARIZATION_POINTS - 1));

        cmsPipelineEvalFloat(InFloat, OutFloat, Src);

        for (j=0; j < Src ->InputChannels; j++)
            GammaTables[j] -> Table16[i] = _cmsQuickSaturateWord(OutFloat[j] * 65535.0);
    }

    ObtainedCurves = cmsStageAllocToneCurves(Src ->ContextID, Src ->InputChannels, GammaTables);
    if (ObtainedCurves == NULL) goto Error;

    for (i=0; i < Src ->InputChannels; i++) {
        cmsFreeToneCurve(GammaTables[i]);
        GammaTables[i] = NULL;
    }

    if (GammaTables != NULL) {
        _cmsFree(Src->ContextID, GammaTables);
        GammaTables = NULL;
    }

    // Maybe the curves are linear at the end
    if (!AllCurvesAreLinear(ObtainedCurves)) {

        if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, ObtainedCurves))
            goto Error;

        // If the curves are to be applied in 8 bits, we can save memory
        if (_cmsFormatterIs8bit(*InputFormat)) {

            _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) ObtainedCurves ->Data;
             Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 256, Data ->TheCurves);

             if (c16 == NULL) goto Error; 
             *dwFlags |= cmsFLAGS_NOCACHE;
            _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves8, c16, CurvesFree, CurvesDup);

        }
        else {

            _cmsStageToneCurvesData* Data = (_cmsStageToneCurvesData*) cmsStageData(ObtainedCurves);
             Curves16Data* c16 = CurvesAlloc(Dest ->ContextID, Data ->nCurves, 65536, Data ->TheCurves);

             if (c16 == NULL) goto Error; 
             *dwFlags |= cmsFLAGS_NOCACHE;
            _cmsPipelineSetOptimizationParameters(Dest, FastEvaluateCurves16, c16, CurvesFree, CurvesDup);
        }
    }
    else {

        // LUT optimizes to nothing. Set the identity LUT
        cmsStageFree(ObtainedCurves);
        ObtainedCurves = NULL;

        if (!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, cmsStageAllocIdentity(Dest ->ContextID, Src ->InputChannels)))
            goto Error;

        *dwFlags |= cmsFLAGS_NOCACHE;
        _cmsPipelineSetOptimizationParameters(Dest, FastIdentity16, (void*) Dest, NULL, NULL);
    }

    // We are done.
    cmsPipelineFree(Src);
    *Lut = Dest;
    return TRUE;

Error:

    if (ObtainedCurves != NULL) cmsStageFree(ObtainedCurves);
    if (GammaTables != NULL) {
        for (i=0; i < Src ->InputChannels; i++) {
            if (GammaTables[i] != NULL) cmsFreeToneCurve(GammaTables[i]);
        }

        _cmsFree(Src ->ContextID, GammaTables);
    }

    if (Dest != NULL) cmsPipelineFree(Dest);
    return FALSE;

    cmsUNUSED_PARAMETER(Intent);
    cmsUNUSED_PARAMETER(InputFormat);
    cmsUNUSED_PARAMETER(OutputFormat);
    cmsUNUSED_PARAMETER(dwFlags);
}

Project: Little-CMS

void DupPluginOptimizationList(struct _cmsContext_struct* ctx, 
                               const struct _cmsContext_struct* src)
{
   _cmsOptimizationPluginChunkType newHead = { NULL };
   _cmsOptimizationCollection*  entry;
   _cmsOptimizationCollection*  Anterior = NULL;
   _cmsOptimizationPluginChunkType* head = (_cmsOptimizationPluginChunkType*) src->chunks[OptimizationPlugin];

    _cmsAssert(ctx != NULL);
    _cmsAssert(head != NULL);

    // Walk the list copying all nodes
   for (entry = head->OptimizationCollection;
        entry != NULL;
        entry = entry ->Next) {

            _cmsOptimizationCollection *newEntry = ( _cmsOptimizationCollection *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsOptimizationCollection));
   
            if (newEntry == NULL) 
                return;

            // We want to keep the linked list order, so this is a little bit tricky
            newEntry -> Next = NULL;
            if (Anterior)
                Anterior -> Next = newEntry;
     
            Anterior = newEntry;

            if (newHead.OptimizationCollection == NULL)
                newHead.OptimizationCollection = newEntry;
    }

  ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsOptimizationPluginChunkType));
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
{
    cmsUInt32Number Before;

     // Special case for undefined strings (see ICC Votable
     // Proposal Submission, Dictionary Type and Metadata TAG Definition)
     if (mlu == NULL) {
        e ->Sizes[i] = 0;
        e ->Offsets[i] = 0;
        return TRUE;
    }

    Before = io ->Tell(io);
    e ->Offsets[i] = Before - BaseOffset;

    if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;

    e ->Sizes[i] = io ->Tell(io) - Before;
    return TRUE;
}

Project: Little-CMS

cmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
{
    cmsCurveSegSignature ElementSig;
    cmsUInt32Number i, j;
    cmsUInt16Number nSegments;
    cmsCurveSegment*  Segments;
    cmsToneCurve* Curve;
    cmsFloat32Number PrevBreak = MINUS_INF;    // - infinite

    // Take signature and channels for each element.
     if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;

     // That should be a segmented curve
     if (ElementSig != cmsSigSegmentedCurve) return NULL;

     if (!_cmsReadUInt32Number(io, NULL)) return NULL;
     if (!_cmsReadUInt16Number(io, &nSegments)) return NULL;
     if (!_cmsReadUInt16Number(io, NULL)) return NULL;

     if (nSegments < 1) return NULL;
     Segments = (cmsCurveSegment*) _cmsCalloc(self ->ContextID, nSegments, sizeof(cmsCurveSegment));
     if (Segments == NULL) return NULL;

     // Read breakpoints
     for (i=0; i < (cmsUInt32Number) nSegments - 1; i++) {

         Segments[i].x0 = PrevBreak;
         if (!_cmsReadFloat32Number(io, &Segments[i].x1)) goto Error;
         PrevBreak = Segments[i].x1;
     }

     Segments[nSegments-1].x0 = PrevBreak;
     Segments[nSegments-1].x1 = PLUS_INF;     // A big cmsFloat32Number number

     // Read segments
     for (i=0; i < nSegments; i++) {

          if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) goto Error;
          if (!_cmsReadUInt32Number(io, NULL)) goto Error;

           switch (ElementSig) {

            case cmsSigFormulaCurveSeg: {

                cmsUInt16Number Type;
                cmsUInt32Number ParamsByType[] = {4, 5, 5 };

                if (!_cmsReadUInt16Number(io, &Type)) goto Error;
                if (!_cmsReadUInt16Number(io, NULL)) goto Error;

                Segments[i].Type = Type + 6;
                if (Type > 2) goto Error;

                for (j=0; j < ParamsByType[Type]; j++) {

                    cmsFloat32Number f;
                    if (!_cmsReadFloat32Number(io, &f)) goto Error;
                    Segments[i].Params[j] = f;
                }
                }
                break;


            case cmsSigSampledCurveSeg: {
                cmsUInt32Number Count;

                if (!_cmsReadUInt32Number(io, &Count)) goto Error;

                Segments[i].nGridPoints = Count;
                Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
                if (Segments[i].SampledPoints == NULL) goto Error;

                for (j=0; j < Count; j++) {
                    if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error;
                }
                }
                break;

            default:
                {
                char String[5];

                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
                cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String);
                }
                goto Error;

         }
     }

     Curve = cmsBuildSegmentedToneCurve(self ->ContextID, nSegments, Segments);

     for (i=0; i < nSegments; i++) {
         if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
     }
     _cmsFree(self ->ContextID, Segments);
     return Curve;

Error:
     if (Segments) {
         for (i=0; i < nSegments; i++) {
             if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
         }
         _cmsFree(self ->ContextID, Segments);
     }
     return NULL;
}

Project: Little-CMS

cmsBool PreOptimize(cmsPipeline* Lut)
{
    cmsBool AnyOpt = FALSE, Opt;

    do {

        Opt = FALSE;

        // Remove all identities
        Opt |= _Remove1Op(Lut, cmsSigIdentityElemType);

        // Remove XYZ2Lab followed by Lab2XYZ
        Opt |= _Remove2Op(Lut, cmsSigXYZ2LabElemType, cmsSigLab2XYZElemType);

        // Remove Lab2XYZ followed by XYZ2Lab
        Opt |= _Remove2Op(Lut, cmsSigLab2XYZElemType, cmsSigXYZ2LabElemType);

        // Remove V4 to V2 followed by V2 to V4
        Opt |= _Remove2Op(Lut, cmsSigLabV4toV2, cmsSigLabV2toV4);

        // Remove V2 to V4 followed by V4 to V2
        Opt |= _Remove2Op(Lut, cmsSigLabV2toV4, cmsSigLabV4toV2);

        // Remove float pcs Lab conversions
        Opt |= _Remove2Op(Lut, cmsSigLab2FloatPCS, cmsSigFloatPCS2Lab);

        // Remove float pcs Lab conversions
        Opt |= _Remove2Op(Lut, cmsSigXYZ2FloatPCS, cmsSigFloatPCS2XYZ);

        // Simplify matrix. 
        Opt |= _MultiplyMatrix(Lut);

        if (Opt) AnyOpt = TRUE;

    } while (Opt);

    return AnyOpt;
}

Project: Little-CMS
File: cmstypes.c

cmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
{
    _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;

    // Write the Matrix
    if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;

    if (m ->Offset != NULL) {

    if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
    if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
    }
    else {
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;

    }


    return TRUE;

    cmsUNUSED_PARAMETER(self);
}

Project: Little-CMS
File: cmstypes.c

cmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsUInt32Number BaseOffset;
    cmsStage* mpe = (cmsStage*) Ptr;
    _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data;

    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // Write the header. Since those are curves, input and output channels are same
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;

    if (!WritePositionTable(self, io, 0,
                                mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;


    return TRUE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS

void FillSecondShaper(cmsUInt16Number* Table, cmsToneCurve* Curve, cmsBool Is8BitsOutput)
{
    int i;
    cmsFloat32Number R, Val;

    for (i=0; i < 16385; i++) {

        R   = (cmsFloat32Number) (i / 16384.0);
        Val = cmsEvalToneCurveFloat(Curve, R);    // Val comes 0..1.0

        if (Val < 0)
            Val = 0;

        if (Val > 1.0)
            Val = 1.0;

        if (Is8BitsOutput) {

            // If 8 bits output, we can optimize further by computing the / 257 part.
            // first we compute the resulting byte and then we store the byte times
            // 257. This quantization allows to round very quick by doing a >> 8, but
            // since the low byte is always equal to msb, we can do a & 0xff and this works!
            cmsUInt16Number w = _cmsQuickSaturateWord(Val * 65535.0);
            cmsUInt8Number  b = FROM_16_TO_8(w);

            Table[i] = FROM_8_TO_16(b);
        }
        else Table[i]  = _cmsQuickSaturateWord(Val * 65535.0);
    }
}

Project: Little-CMS
File: cmstypes.c

void *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsCIExyYTRIPLE* chrm;
    cmsUInt16Number nChans, Table;

    *nItems = 0;
    chrm =  (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE));
    if (chrm == NULL) return NULL;

    if (!_cmsReadUInt16Number(io, &nChans)) goto Error;

    // Let's recover from a bug introduced in early versions of lcms1
    if (nChans == 0 && SizeOfTag == 32) {

        if (!_cmsReadUInt16Number(io, NULL)) goto Error;
        if (!_cmsReadUInt16Number(io, &nChans)) goto Error;
    }

    if (nChans != 3) goto Error;

    if (!_cmsReadUInt16Number(io, &Table)) goto Error;

    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error;
    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error;

    chrm ->Red.Y = 1.0;

    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error;
    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error;

    chrm ->Green.Y = 1.0;

    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error;
    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error;

    chrm ->Blue.Y = 1.0;

    *nItems = 1;
    return (void*) chrm;

Error:
    _cmsFree(self ->ContextID, (void*) chrm);
    return NULL;

    cmsUNUSED_PARAMETER(SizeOfTag);
}

Project: Little-CMS
File: cmstypes.c

cmsBool WritePositionTable(struct _cms_typehandler_struct* self,
                               cmsIOHANDLER* io,
                               cmsUInt32Number SizeOfTag,
                               cmsUInt32Number Count,
                               cmsUInt32Number BaseOffset,
                               void *Cargo,
                               PositionTableEntryFn ElementFn)
{
    cmsUInt32Number i;
    cmsUInt32Number DirectoryPos, CurrentPos, Before;
    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;

     // Create table
    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
    if (ElementOffsets == NULL) goto Error;

    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
    if (ElementSizes == NULL) goto Error;

    // Keep starting position of curve offsets
    DirectoryPos = io ->Tell(io);
  
    // Write a fake directory to be filled latter on
    for (i=0; i < Count; i++) {

        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
    }

    // Write each element. Keep track of the size as well.
    for (i=0; i < Count; i++) {

        Before = io ->Tell(io);
        ElementOffsets[i] = Before - BaseOffset;

        // Callback to write...
        if (!ElementFn(self, io, Cargo, i, SizeOfTag)) goto Error;

        // Now the size
        ElementSizes[i] = io ->Tell(io) - Before;
    }

    // Write the directory
    CurrentPos = io ->Tell(io);
    if (!io ->Seek(io, DirectoryPos)) goto Error;

    for (i=0; i <  Count; i++) {
        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
    }

    if (!io ->Seek(io, CurrentPos)) goto Error;

    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
    return TRUE;

Error:
    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
    return FALSE;
}

Project: Little-CMS

Curves16Data* CurvesAlloc(cmsContext ContextID, int nCurves, int nElements, cmsToneCurve** G)
{
    int i, j;
    Curves16Data* c16;

    c16 = (Curves16Data*)_cmsMallocZero(ContextID, sizeof(Curves16Data));
    if (c16 == NULL) return NULL;

    c16 ->nCurves = nCurves;
    c16 ->nElements = nElements;

    c16->Curves = (cmsUInt16Number**) _cmsCalloc(ContextID, nCurves, sizeof(cmsUInt16Number*));
    if (c16->Curves == NULL) {
        _cmsFree(ContextID, c16);
        return NULL;
    }

    for (i=0; i < nCurves; i++) {

        c16->Curves[i] = (cmsUInt16Number*) _cmsCalloc(ContextID, nElements, sizeof(cmsUInt16Number));

        if (c16->Curves[i] == NULL) {

            for (j=0; j < i; j++) {
                _cmsFree(ContextID, c16->Curves[j]);
            }
            _cmsFree(ContextID, c16->Curves);
            _cmsFree(ContextID, c16);
            return NULL;
        }

        if (nElements == 256) {

            for (j=0; j < nElements; j++) {

                c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], FROM_8_TO_16(j));
            }
        }
        else {

            for (j=0; j < nElements; j++) {
                c16 ->Curves[i][j] = cmsEvalToneCurve16(G[i], (cmsUInt16Number) j);
            }
        }
    }

    return c16;
}

Project: Little-CMS
File: cmstypes.c

void *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsSEQ* OutSeq;
    cmsUInt32Number Count;
    cmsUInt32Number BaseOffset;

    *nItems = 0;

    // Get actual position as a basis for element offsets
    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // Get table count
    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);

    // Allocate an empty structure
    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
    if (OutSeq == NULL) return NULL;


    // Read the position table
    if (!ReadPositionTable(self, io, Count, BaseOffset, OutSeq, ReadSeqID)) {

        cmsFreeProfileSequenceDescription(OutSeq);
        return NULL;
    }

    // Success
    *nItems = 1;
    return OutSeq;

}

Project: Little-CMS
File: cmstypes.c

cmsBool ReadOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr)
{

    cmsUInt32Number nChars;

      // Special case for undefined strings (see ICC Votable
      // Proposal Submission, Dictionary Type and Metadata TAG Definition)
      if (e -> Offsets[i] == 0) {

          *wcstr = NULL;
          return TRUE;
      }

      if (!io -> Seek(io, e -> Offsets[i])) return FALSE;

      nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);


      *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
      if (*wcstr == NULL) return FALSE;

      if (!_cmsReadWCharArray(io, nChars, *wcstr)) {
          _cmsFree(e ->ContextID, *wcstr);
          return FALSE;
      }

      // End of string marker
      (*wcstr)[nChars] = 0;
      return TRUE;
}

Project: Little-CMS

Prelin8Data* PrelinOpt8alloc(cmsContext ContextID, const cmsInterpParams* p, cmsToneCurve* G[3])
{
    int i;
    cmsUInt16Number Input[3];
    cmsS15Fixed16Number v1, v2, v3;
    Prelin8Data* p8;

    p8 = (Prelin8Data*)_cmsMallocZero(ContextID, sizeof(Prelin8Data));
    if (p8 == NULL) return NULL;

    // Since this only works for 8 bit input, values comes always as x * 257,
    // we can safely take msb byte (x << 8 + x)

    for (i=0; i < 256; i++) {

        if (G != NULL) {

            // Get 16-bit representation
            Input[0] = cmsEvalToneCurve16(G[0], FROM_8_TO_16(i));
            Input[1] = cmsEvalToneCurve16(G[1], FROM_8_TO_16(i));
            Input[2] = cmsEvalToneCurve16(G[2], FROM_8_TO_16(i));
        }
        else {
            Input[0] = FROM_8_TO_16(i);
            Input[1] = FROM_8_TO_16(i);
            Input[2] = FROM_8_TO_16(i);
        }


        // Move to 0..1.0 in fixed domain
        v1 = _cmsToFixedDomain(Input[0] * p -> Domain[0]);
        v2 = _cmsToFixedDomain(Input[1] * p -> Domain[1]);
        v3 = _cmsToFixedDomain(Input[2] * p -> Domain[2]);

        // Store the precalculated table of nodes
        p8 ->X0[i] = (p->opta[2] * FIXED_TO_INT(v1));
        p8 ->Y0[i] = (p->opta[1] * FIXED_TO_INT(v2));
        p8 ->Z0[i] = (p->opta[0] * FIXED_TO_INT(v3));

        // Store the precalculated table of offsets
        p8 ->rx[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v1);
        p8 ->ry[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v2);
        p8 ->rz[i] = (cmsUInt16Number) FIXED_REST_TO_INT(v3);
    }

    p8 ->ContextID = ContextID;
    p8 ->p = p;

    return p8;
}

Project: Little-CMS
File: cmstypes.c

cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
{
    cmsUInt32Number i, n;
    cmsTagTypeSignature CurrentType;
    cmsToneCurve** Curves;


    n      = cmsStageOutputChannels(mpe);
    Curves = _cmsStageGetPtrToCurveSet(mpe);

    for (i=0; i < n; i++) {

        // If this is a table-based curve, use curve type even on V4
        CurrentType = Type;

        if ((Curves[i] ->nSegments == 0)||
            ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) )
            CurrentType = cmsSigCurveType;
        else
        if (Curves[i] ->Segments[0].Type < 0)
            CurrentType = cmsSigCurveType;

        if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE;

        switch (CurrentType) {

            case cmsSigCurveType:
                if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE;
                break;

            case cmsSigParametricCurveType:
                if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE;
                break;

            default:
                {
                    char String[5];

                    _cmsTagSignature2String(String, (cmsTagSignature) Type);
                    cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve type '%s'", String);
                }
                return FALSE;
        }

        if (!_cmsWriteAlignment(io)) return FALSE;
    }


    return TRUE;
}

Project: Little-CMS
File: cmstypes.c

cmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
{
    cmsHANDLE hDict = (cmsHANDLE) Ptr;
    const cmsDICTentry* p;
    cmsBool AnyName, AnyValue;
    cmsUInt32Number i, Count, Length;
    cmsUInt32Number DirectoryPos, CurrentPos, BaseOffset;
   _cmsDICarray a;

    if (hDict == NULL) return FALSE;

    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);

    // Let's inspect the dictionary
    Count = 0; AnyName = FALSE; AnyValue = FALSE;
    for (p = cmsDictGetEntryList(hDict); p != NULL; p = cmsDictNextEntry(p)) {

        if (p ->DisplayName != NULL) AnyName = TRUE;
        if (p ->DisplayValue != NULL) AnyValue = TRUE;
        Count++;
    }

    Length = 16;
    if (AnyName)  Length += 8;
    if (AnyValue) Length += 8;

    if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
    if (!_cmsWriteUInt32Number(io, Length)) return FALSE;

    // Keep starting position of offsets table
    DirectoryPos = io ->Tell(io);

    // Allocate offsets array
    if (!AllocArray(self ->ContextID, &a, Count, Length)) goto Error;

    // Write a fake directory to be filled latter on
    if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;

    // Write each element. Keep track of the size as well.
    p = cmsDictGetEntryList(hDict);
    for (i=0; i < Count; i++) {

        if (!WriteOneWChar(io, &a.Name, i,  p ->Name, BaseOffset)) goto Error;
        if (!WriteOneWChar(io, &a.Value, i, p ->Value, BaseOffset)) goto Error;

        if (p ->DisplayName != NULL) {
            if (!WriteOneMLUC(self, io, &a.DisplayName, i, p ->DisplayName, BaseOffset)) goto Error;
        }

        if (p ->DisplayValue != NULL) {
            if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error;
        }

       p = cmsDictNextEntry(p);
    }

    // Write the directory
    CurrentPos = io ->Tell(io);
    if (!io ->Seek(io, DirectoryPos)) goto Error;

    if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;

    if (!io ->Seek(io, CurrentPos)) goto Error;

    FreeArray(&a);
    return TRUE;

Error:
    FreeArray(&a);
    return FALSE;

    cmsUNUSED_PARAMETER(nItems);
}

Project: Little-CMS

cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
                              cmsIOHANDLER* io,
                              cmsUInt32Number Count,
                              cmsUInt32Number BaseOffset,
                              void *Cargo,
                              PositionTableEntryFn ElementFn)
{
    cmsUInt32Number i;
    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
    cmsUInt32Number currentPosition;

    currentPosition = io->Tell(io);

    // Verify there is enough space left to read at least two cmsUInt32Number items for Count items.
    if (((io->ReportedSize - currentPosition) / (2 * sizeof(cmsUInt32Number))) < Count)
        return FALSE;

    // Let's take the offsets to each element
    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
    if (ElementOffsets == NULL) goto Error;

    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
    if (ElementSizes == NULL) goto Error;

    for (i=0; i < Count; i++) {

        if (!_cmsReadUInt32Number(io, &ElementOffsets[i])) goto Error;
        if (!_cmsReadUInt32Number(io, &ElementSizes[i])) goto Error;

        ElementOffsets[i] += BaseOffset;
    }

    // Seek to each element and read it
    for (i=0; i < Count; i++) {

        if (!io -> Seek(io, ElementOffsets[i])) goto Error;

        // This is the reader callback
        if (!ElementFn(self, io, Cargo, i, ElementSizes[i])) goto Error;
    }

    // Success
    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
    return TRUE;

Error:
    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
    return FALSE;
}

Project: Little-CMS

void PrelinEval8(register const cmsUInt16Number Input[],
                  register cmsUInt16Number Output[],
                  register const void* D)
{

    cmsUInt8Number         r, g, b;
    cmsS15Fixed16Number    rx, ry, rz;
    cmsS15Fixed16Number    c0, c1, c2, c3, Rest;
    int                    OutChan;
    register cmsS15Fixed16Number    X0, X1, Y0, Y1, Z0, Z1;
    Prelin8Data* p8 = (Prelin8Data*) D;
    register const cmsInterpParams* p = p8 ->p;
    int                    TotalOut = p -> nOutputs;
    const cmsUInt16Number* LutTable = (const cmsUInt16Number*) p->Table;

    r = Input[0] >> 8;
    g = Input[1] >> 8;
    b = Input[2] >> 8;

    X0 = X1 = p8->X0[r];
    Y0 = Y1 = p8->Y0[g];
    Z0 = Z1 = p8->Z0[b];

    rx = p8 ->rx[r];
    ry = p8 ->ry[g];
    rz = p8 ->rz[b];

    X1 = X0 + ((rx == 0) ? 0 : p ->opta[2]);
    Y1 = Y0 + ((ry == 0) ? 0 : p ->opta[1]);
    Z1 = Z0 + ((rz == 0) ? 0 : p ->opta[0]);


    // These are the 6 Tetrahedral
    for (OutChan=0; OutChan < TotalOut; OutChan++) {

        c0 = DENS(X0, Y0, Z0);

        if (rx >= ry && ry >= rz)
        {
            c1 = DENS(X1, Y0, Z0) - c0;
            c2 = DENS(X1, Y1, Z0) - DENS(X1, Y0, Z0);
            c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
        }
        else
            if (rx >= rz && rz >= ry)
            {
                c1 = DENS(X1, Y0, Z0) - c0;
                c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                c3 = DENS(X1, Y0, Z1) - DENS(X1, Y0, Z0);
            }
            else
                if (rz >= rx && rx >= ry)
                {
                    c1 = DENS(X1, Y0, Z1) - DENS(X0, Y0, Z1);
                    c2 = DENS(X1, Y1, Z1) - DENS(X1, Y0, Z1);
                    c3 = DENS(X0, Y0, Z1) - c0;
                }
                else
                    if (ry >= rx && rx >= rz)
                    {
                        c1 = DENS(X1, Y1, Z0) - DENS(X0, Y1, Z0);
                        c2 = DENS(X0, Y1, Z0) - c0;
                        c3 = DENS(X1, Y1, Z1) - DENS(X1, Y1, Z0);
                    }
                    else
                        if (ry >= rz && rz >= rx)
                        {
                            c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                            c2 = DENS(X0, Y1, Z0) - c0;
                            c3 = DENS(X0, Y1, Z1) - DENS(X0, Y1, Z0);
                        }
                        else
                            if (rz >= ry && ry >= rx)
                            {
                                c1 = DENS(X1, Y1, Z1) - DENS(X0, Y1, Z1);
                                c2 = DENS(X0, Y1, Z1) - DENS(X0, Y0, Z1);
                                c3 = DENS(X0, Y0, Z1) - c0;
                            }
                            else  {
                                c1 = c2 = c3 = 0;
                            }


                            Rest = c1 * rx + c2 * ry + c3 * rz + 0x8001;
                            Output[OutChan] = (cmsUInt16Number)c0 + ((Rest + (Rest >> 16)) >> 16);

    }
}

Project: Little-CMS

cmsBool WhitesAreEqual(int n, cmsUInt16Number White1[], cmsUInt16Number White2[] )
{
    int i;

    for (i=0; i < n; i++) {

        if (abs(White1[i] - White2[i]) > 0xf000) return TRUE;  // Values are so extremely different that the fixup should be avoided
        if (White1[i] != White2[i]) return FALSE;
    }
    return TRUE;
}

Project: Little-CMS

cmsBool OptimizeByResampling(cmsPipeline** Lut, cmsUInt32Number Intent, cmsUInt32Number* InputFormat, cmsUInt32Number* OutputFormat, cmsUInt32Number* dwFlags)
{
    cmsPipeline* Src = NULL;
    cmsPipeline* Dest = NULL;
    cmsStage* mpe;
    cmsStage* CLUT;
    cmsStage *KeepPreLin = NULL, *KeepPostLin = NULL;
    int nGridPoints;
    cmsColorSpaceSignature ColorSpace, OutputColorSpace;
    cmsStage *NewPreLin = NULL;
    cmsStage *NewPostLin = NULL;
    _cmsStageCLutData* DataCLUT;
    cmsToneCurve** DataSetIn;
    cmsToneCurve** DataSetOut;
    Prelin16Data* p16;

    // This is a loosy optimization! does not apply in floating-point cases
    if (_cmsFormatterIsFloat(*InputFormat) || _cmsFormatterIsFloat(*OutputFormat)) return FALSE;

    ColorSpace       = _cmsICCcolorSpace(T_COLORSPACE(*InputFormat));
    OutputColorSpace = _cmsICCcolorSpace(T_COLORSPACE(*OutputFormat));

    // Color space must be specified
    if (ColorSpace == (cmsColorSpaceSignature)-1 ||
        OutputColorSpace == (cmsColorSpaceSignature)-1) return FALSE;

    nGridPoints      = _cmsReasonableGridpointsByColorspace(ColorSpace, *dwFlags);

    // For empty LUTs, 2 points are enough
    if (cmsPipelineStageCount(*Lut) == 0)
        nGridPoints = 2;

    Src = *Lut;

    // Named color pipelines cannot be optimized either
    for (mpe = cmsPipelineGetPtrToFirstStage(Src);
        mpe != NULL;
        mpe = cmsStageNext(mpe)) {
            if (cmsStageType(mpe) == cmsSigNamedColorElemType) return FALSE;
    }

    // Allocate an empty LUT
    Dest =  cmsPipelineAlloc(Src ->ContextID, Src ->InputChannels, Src ->OutputChannels);
    if (!Dest) return FALSE;

    // Prelinearization tables are kept unless indicated by flags
    if (*dwFlags & cmsFLAGS_CLUT_PRE_LINEARIZATION) {

        // Get a pointer to the prelinearization element
        cmsStage* PreLin = cmsPipelineGetPtrToFirstStage(Src);

        // Check if suitable
        if (PreLin && PreLin ->Type == cmsSigCurveSetElemType) {

            // Maybe this is a linear tram, so we can avoid the whole stuff
            if (!AllCurvesAreLinear(PreLin)) {

                // All seems ok, proceed.
                NewPreLin = cmsStageDup(PreLin);
                if(!cmsPipelineInsertStage(Dest, cmsAT_BEGIN, NewPreLin))
                    goto Error;

                // Remove prelinearization. Since we have duplicated the curve
                // in destination LUT, the sampling should be applied after this stage.
                cmsPipelineUnlinkStage(Src, cmsAT_BEGIN, &KeepPreLin);
            }
        }
    }

    // Allocate the CLUT
    CLUT = cmsStageAllocCLut16bit(Src ->ContextID, nGridPoints, Src ->InputChannels, Src->OutputChannels, NULL);
    if (CLUT == NULL) goto Error;

    // Add the CLUT to the destination LUT
    if (!cmsPipelineInsertStage(Dest, cmsAT_END, CLUT)) {
        goto Error;
    }

    // Postlinearization tables are kept unless indicated by flags
    if (*dwFlags & cmsFLAGS_CLUT_POST_LINEARIZATION) {

        // Get a pointer to the postlinearization if present
        cmsStage* PostLin = cmsPipelineGetPtrToLastStage(Src);

        // Check if suitable
        if (PostLin && cmsStageType(PostLin) == cmsSigCurveSetElemType) {

            // Maybe this is a linear tram, so we can avoid the whole stuff
            if (!AllCurvesAreLinear(PostLin)) {

                // All seems ok, proceed.
                NewPostLin = cmsStageDup(PostLin);
                if (!cmsPipelineInsertStage(Dest, cmsAT_END, NewPostLin))
                    goto Error;

                // In destination LUT, the sampling should be applied after this stage.
                cmsPipelineUnlinkStage(Src, cmsAT_END, &KeepPostLin);
            }
        }
    }

    // Now its time to do the sampling. We have to ignore pre/post linearization
    // The source LUT without pre/post curves is passed as parameter.
    if (!cmsStageSampleCLut16bit(CLUT, XFormSampler16, (void*) Src, 0)) {
Error:
        // Ops, something went wrong, Restore stages
        if (KeepPreLin != NULL) {
            if (!cmsPipelineInsertStage(Src, cmsAT_BEGIN, KeepPreLin)) {
                _cmsAssert(0); // This never happens
            }
        }
        if (KeepPostLin != NULL) {
            if (!cmsPipelineInsertStage(Src, cmsAT_END,   KeepPostLin)) {
                _cmsAssert(0); // This never happens
            }
        }
        cmsPipelineFree(Dest);
        return FALSE;
    }

    // Done.

    if (KeepPreLin != NULL) cmsStageFree(KeepPreLin);
    if (KeepPostLin != NULL) cmsStageFree(KeepPostLin);
    cmsPipelineFree(Src);

    DataCLUT = (_cmsStageCLutData*) CLUT ->Data;

    if (NewPreLin == NULL) DataSetIn = NULL;
    else DataSetIn = ((_cmsStageToneCurvesData*) NewPreLin ->Data) ->TheCurves;

    if (NewPostLin == NULL) DataSetOut = NULL;
    else  DataSetOut = ((_cmsStageToneCurvesData*) NewPostLin ->Data) ->TheCurves;


    if (DataSetIn == NULL && DataSetOut == NULL) {

        _cmsPipelineSetOptimizationParameters(Dest, (_cmsOPTeval16Fn) DataCLUT->Params->Interpolation.Lerp16, DataCLUT->Params, NULL, NULL);
    }
    else {

        p16 = PrelinOpt16alloc(Dest ->ContextID,
            DataCLUT ->Params,
            Dest ->InputChannels,
            DataSetIn,
            Dest ->OutputChannels,
            DataSetOut);

        _cmsPipelineSetOptimizationParameters(Dest, PrelinEval16, (void*) p16, PrelinOpt16free, Prelin16dup);
    }


    // Don't fix white on absolute colorimetric
    if (Intent == INTENT_ABSOLUTE_COLORIMETRIC)
        *dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP;

    if (!(*dwFlags & cmsFLAGS_NOWHITEONWHITEFIXUP)) {

        FixWhiteMisalignment(Dest, ColorSpace, OutputColorSpace);
    }

    *Lut = Dest;
    return TRUE;

    cmsUNUSED_PARAMETER(Intent);
}

Project: Little-CMS
File: cmstypes.c

void *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    cmsSEQ* OutSeq;
    cmsUInt32Number i, Count;

    *nItems = 0;

    if (!_cmsReadUInt32Number(io, &Count)) return NULL;

    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
    SizeOfTag -= sizeof(cmsUInt32Number);


    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
    if (OutSeq == NULL) return NULL;

    OutSeq ->n = Count;

    // Get structures as well

    for (i=0; i < Count; i++) {

        cmsPSEQDESC* sec = &OutSeq -> seq[i];

        if (!_cmsReadUInt32Number(io, &sec ->deviceMfg)) goto Error;
        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
        SizeOfTag -= sizeof(cmsUInt32Number);

        if (!_cmsReadUInt32Number(io, &sec ->deviceModel)) goto Error;
        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
        SizeOfTag -= sizeof(cmsUInt32Number);

        if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error;
        if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error;
        SizeOfTag -= sizeof(cmsUInt64Number);

        if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error;
        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
        SizeOfTag -= sizeof(cmsUInt32Number);

        if (!ReadEmbeddedText(self, io, &sec ->Manufacturer, SizeOfTag)) goto Error;
        if (!ReadEmbeddedText(self, io, &sec ->Model, SizeOfTag)) goto Error;
    }

    *nItems = 1;
    return OutSeq;

Error:
    cmsFreeProfileSequenceDescription(OutSeq);
    return NULL;
}

Project: Little-CMS
File: cmstypes.c

void _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx, 
                               const struct _cmsContext_struct* src)
{
    if (src != NULL) {
        
        // Duplicate the LIST
        DupTagTypeList(ctx, src, MPEPlugin);
    }
    else {
        static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
        ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
    }

}

Project: Little-CMS

void  _cmsAllocOptimizationPluginChunk(struct _cmsContext_struct* ctx, 
                                         const struct _cmsContext_struct* src)
{
  if (src != NULL) {

        // Copy all linked list
       DupPluginOptimizationList(ctx, src);
    }
    else {
        static _cmsOptimizationPluginChunkType OptimizationPluginChunkType = { NULL };
        ctx ->chunks[OptimizationPlugin] = _cmsSubAllocDup(ctx ->MemPool, &OptimizationPluginChunkType, sizeof(_cmsOptimizationPluginChunkType));
    }
}

Project: Little-CMS
File: cmstypes.c

void *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
{
    char* Text = NULL;
    cmsMLU* mlu = NULL;

    // Create a container
    mlu = cmsMLUalloc(self ->ContextID, 1);
    if (mlu == NULL) return NULL;

    *nItems = 0;

    // We need to store the "\0" at the end, so +1
    if (SizeOfTag == UINT_MAX) goto Error;

    Text = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
    if (Text == NULL) goto Error;

    if (io -> Read(io, Text, sizeof(char), SizeOfTag) != SizeOfTag) goto Error;

    // Make sure text is properly ended
    Text[SizeOfTag] = 0;
    *nItems = 1;

    // Keep the result
    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;

    _cmsFree(self ->ContextID, Text);
    return (void*) mlu;

Error:
    if (mlu != NULL)
        cmsMLUfree(mlu);
    if (Text != NULL)
        _cmsFree(self ->ContextID, Text);

    return NULL;
}