Example #1
0
// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
// Note that because extended range, we can use a -1.0 value for out of gamut in this case.
static
void FloatXFORM(_cmsTRANSFORM* p,
                const void* in,
                void* out, cmsUInt32Number Size, cmsUInt32Number Stride)
{
    cmsUInt8Number* accum;
    cmsUInt8Number* output;
    cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
    cmsFloat32Number OutOfGamut;
    cmsUInt32Number i, j;

    accum  = (cmsUInt8Number*)  in;
    output = (cmsUInt8Number*)  out;

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

        accum = p -> FromInputFloat(p, fIn, accum, Stride);

        // Any gamut chack to do?
        if (p ->GamutCheck != NULL) {

            // Evaluate gamut marker.
            cmsPipelineEvalFloat( fIn, &OutOfGamut, p ->GamutCheck);

            // Is current color out of gamut?
            if (OutOfGamut > 0.0) {

                // Certainly, out of gamut
                for (j=0; j < cmsMAXCHANNELS; j++)
                    fOut[j] = -1.0;

            }
            else {
                // No, proceed normally
                cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
            }
        }
        else {

            // No gamut check at all
            cmsPipelineEvalFloat(fIn, fOut, p -> Lut);
        }

        // Back to asked representation
        output = p -> ToOutputFloat(p, fOut, output, Stride);
    }
}
Example #2
0
// The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision
static
int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
{
    int i;
    cmsFloat32Number Inf[4], Outf[4];
    cmsFloat32Number LabK[4];
    cmsFloat64Number SumCMY, SumCMYK, Error, Ratio;
    cmsCIELab ColorimetricLab, BlackPreservingLab;
    PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo;

    // Convert from 16 bits to floating point
    for (i=0; i < 4; i++)
        Inf[i] = (cmsFloat32Number) (In[i] / 65535.0);

    // Get the K across Tone curve
    LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]);

    // If going across black only, keep black only
    if (In[0] == 0 && In[1] == 0 && In[2] == 0) {

        Out[0] = Out[1] = Out[2] = 0;
        Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0);
        return TRUE;
    }

    // Try the original transform,
    cmsPipelineEvalFloat( Inf, Outf, bp ->cmyk2cmyk);

    // Store a copy of the floating point result into 16-bit
    for (i=0; i < 4; i++)
            Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0);

    // Maybe K is already ok (mostly on K=0)
    if ( fabs(Outf[3] - LabK[3]) < (3.0 / 65535.0) ) {
        return TRUE;
    }

    // K differ, mesure and keep Lab measurement for further usage
    // this is done in relative colorimetric intent
    cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);

    // Is not black only and the transform doesn't keep black.
    // Obtain the Lab of output CMYK. After that we have Lab + K
    cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1);

    // Obtain the corresponding CMY using reverse interpolation
    // (K is fixed in LabK[3])
    if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) {

        // Cannot find a suitable value, so use colorimetric xform
        // which is already stored in Out[]
        return TRUE;
    }

    // Make sure to pass thru K (which now is fixed)
    Outf[3] = LabK[3];

    // Apply TAC if needed
    SumCMY   = Outf[0]  + Outf[1] + Outf[2];
    SumCMYK  = SumCMY + Outf[3];

    if (SumCMYK > bp ->MaxTAC) {

        Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
        if (Ratio < 0)
            Ratio = 0;
    }
    else
       Ratio = 1.0;

    Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0);     // C
    Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0);     // M
    Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0);     // Y
    Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0);

    // Estimate the error (this goes 16 bits to Lab DBL)
    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
    if (Error > bp -> MaxError)
        bp->MaxError = Error;

    return TRUE;
}
Example #3
0
// Float xform converts floats. Since there are no performance issues, one routine does all job, including gamut check.
// Note that because extended range, we can use a -1.0 value for out of gamut in this case.
static
void FloatXFORM(_cmsTRANSFORM* p,
                const void* in,
                void* out, 
                cmsUInt32Number PixelsPerLine,
                cmsUInt32Number LineCount,
                const cmsStride* Stride)
{
    cmsUInt8Number* accum;
    cmsUInt8Number* output;
    cmsFloat32Number fIn[cmsMAXCHANNELS], fOut[cmsMAXCHANNELS];
    cmsFloat32Number OutOfGamut;
    cmsUInt32Number i, j, c, strideIn, strideOut;

    _cmsHandleExtraChannels(p, in, out, PixelsPerLine, LineCount, Stride);

    strideIn = 0;
    strideOut = 0;

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

        accum = (cmsUInt8Number*)in + strideIn;
        output = (cmsUInt8Number*)out + strideOut;

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

            accum = p->FromInputFloat(p, fIn, accum, Stride->BytesPerPlaneIn);

            // Any gamut chack to do?
            if (p->GamutCheck != NULL) {

                // Evaluate gamut marker.
                cmsPipelineEvalFloat(fIn, &OutOfGamut, p->GamutCheck);

                // Is current color out of gamut?
                if (OutOfGamut > 0.0) {

                    // Certainly, out of gamut
                    for (c = 0; c < cmsMAXCHANNELS; c++)
                        fOut[c] = -1.0;

                }
                else {
                    // No, proceed normally
                    cmsPipelineEvalFloat(fIn, fOut, p->Lut);
                }
            }
            else {

                // No gamut check at all
                cmsPipelineEvalFloat(fIn, fOut, p->Lut);
            }


            output = p->ToOutputFloat(p, fOut, output, Stride->BytesPerPlaneOut);
        }

        strideIn += Stride->BytesPerLineIn;
        strideOut += Stride->BytesPerLineOut;
    }

}