Dear all,


we are trying to use the “Perserve Black functionality” using version 1.18.


We actually want that it only impacts CMYK inputs were C=M=Y=0 and then preserve the incoming K value. We actually want to keep text defined in the input color space as 0,0,0,K to transform into the output color space the same without any color transformation to apply, but we would not want to impact any other colors with C or M or Y not being zero in order to not impact any images.


We understand that the first part of the code does this:

int BlackPreservingSampler(register WORD In[], register WORD Out[], register LPVOID Cargo)



    WORD LabK[4];  

    double SumCMY, SumCMYK, Error;

    cmsCIELab ColorimetricLab, BlackPreservingLab;

    BPCARGO* bp = (LPBPCARGO) Cargo;


    // Get the K across Tone curve

    LabK[3] = cmsLinearInterpLUT16(In[3], bp->KTone ->GammaTable, &bp->KToneParams);  è We also don’t understand this line??


    // 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] = LabK[3];

        return 1;




But we are not sure what the second part of the code does?

    // Try the original transform, maybe K is already ok (valid on K=0)

    cmsDoTransform(bp ->cmyk2cmyk, In, Out, 1);

    if (Out[3] == LabK[3]) return 1;



    // No, mesure and keep Lab measurement for further usage   

    cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);


    // Is not black only and the transform doesn't keep black.

    // Obtain the Lab of CMYK. After that we have Lab + K

    cmsDoTransform(bp ->cmyk2Lab, In, LabK, 1);


    // Obtain the corresponding CMY using reverse interpolation.

    // As a seed, we use the colorimetric CMY

    cmsEvalLUTreverse(bp ->LabK2cmyk, LabK, Out, Out);


    // Estimate the error

    cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1); 

    Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);



    // Apply TAC if needed


    SumCMY   = Out[0]  + Out[1] + Out[2];

    SumCMYK  = SumCMY + Out[3];     


    if (SumCMYK > bp ->MaxTAC) {


        double Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);

        if (Ratio < 0)

                  Ratio = 0;


        Out[0] = (WORD) floor(Out[0] * Ratio + 0.5);     // C

        Out[1] = (WORD) floor(Out[1] * Ratio + 0.5);     // M

        Out[2] = (WORD) floor(Out[2] * Ratio + 0.5);     // Y



    return 1;



We highly appreciate your answer.


Thanks a lot.


Best regards,