< prev index next >

src/java.desktop/share/native/liblcms/cmscnvrt.c

Print this page




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2017 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------
  54 //
  55 
  56 #include "lcms2_internal.h"
  57 
  58 
  59 // Link several profiles to obtain a single LUT modelling the whole color transform. Intents, Black point
  60 // compensation and Adaptation parameters may vary across profiles. BPC and Adaptation refers to the PCS
  61 // after the profile. I.e, BPC[0] refers to connexion between profile(0) and profile(1)
  62 cmsPipeline* _cmsLinkProfiles(cmsContext     ContextID,
  63                               cmsUInt32Number nProfiles,
  64                               cmsUInt32Number Intents[],
  65                               cmsHPROFILE     hProfiles[],
  66                               cmsBool         BPC[],
  67                               cmsFloat64Number AdaptationStates[],
  68                               cmsUInt32Number dwFlags);
  69 
  70 //---------------------------------------------------------------------------------
  71 
  72 // This is the default routine for ICC-style intents. A user may decide to override it by using a plugin.
  73 // Supported intents are perceptual, relative colorimetric, saturation and ICC-absolute colorimetric
  74 static
  75 cmsPipeline* DefaultICCintents(cmsContext     ContextID,
  76                                cmsUInt32Number nProfiles,
  77                                cmsUInt32Number Intents[],
  78                                cmsHPROFILE     hProfiles[],
  79                                cmsBool         BPC[],
  80                                cmsFloat64Number AdaptationStates[],
  81                                cmsUInt32Number dwFlags);
  82 
  83 //---------------------------------------------------------------------------------
  84 
  85 // This is the entry for black-preserving K-only intents, which are non-ICC. Last profile have to be a output profile
  86 // to do the trick (no devicelinks allowed at that position)
  87 static
  88 cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
  89                                           cmsUInt32Number nProfiles,
  90                                           cmsUInt32Number Intents[],
  91                                           cmsHPROFILE     hProfiles[],


 722 
 723         case INTENT_PRESERVE_K_ONLY_SATURATION:
 724         case INTENT_PRESERVE_K_PLANE_SATURATION:
 725             return INTENT_SATURATION;
 726 
 727         default: return Intent;
 728     }
 729 }
 730 
 731 // Sampler for Black-only preserving CMYK->CMYK transforms
 732 
 733 typedef struct {
 734     cmsPipeline*    cmyk2cmyk;      // The original transform
 735     cmsToneCurve*   KTone;          // Black-to-black tone curve
 736 
 737 } GrayOnlyParams;
 738 
 739 
 740 // Preserve black only if that is the only ink used
 741 static
 742 int BlackPreservingGrayOnlySampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 743 {
 744     GrayOnlyParams* bp = (GrayOnlyParams*) Cargo;
 745 
 746     // If going across black only, keep black only
 747     if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 748 
 749         // TAC does not apply because it is black ink!
 750         Out[0] = Out[1] = Out[2] = 0;
 751         Out[3] = cmsEvalToneCurve16(bp->KTone, In[3]);
 752         return TRUE;
 753     }
 754 
 755     // Keep normal transform for other colors
 756     bp ->cmyk2cmyk ->Eval16Fn(In, Out, bp ->cmyk2cmyk->Data);
 757     return TRUE;
 758 }
 759 
 760 // This is the entry for black-preserving K-only intents, which are non-ICC
 761 static
 762 cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,


 849 // K Plane-preserving CMYK to CMYK ------------------------------------------------------------------------------------
 850 
 851 typedef struct {
 852 
 853     cmsPipeline*     cmyk2cmyk;     // The original transform
 854     cmsHTRANSFORM    hProofOutput;  // Output CMYK to Lab (last profile)
 855     cmsHTRANSFORM    cmyk2Lab;      // The input chain
 856     cmsToneCurve*    KTone;         // Black-to-black tone curve
 857     cmsPipeline*     LabK2cmyk;     // The output profile
 858     cmsFloat64Number MaxError;
 859 
 860     cmsHTRANSFORM    hRoundTrip;
 861     cmsFloat64Number MaxTAC;
 862 
 863 
 864 } PreserveKPlaneParams;
 865 
 866 
 867 // The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision
 868 static
 869 int BlackPreservingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
 870 {
 871     int i;
 872     cmsFloat32Number Inf[4], Outf[4];
 873     cmsFloat32Number LabK[4];
 874     cmsFloat64Number SumCMY, SumCMYK, Error, Ratio;
 875     cmsCIELab ColorimetricLab, BlackPreservingLab;
 876     PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo;
 877 
 878     // Convert from 16 bits to floating point
 879     for (i=0; i < 4; i++)
 880         Inf[i] = (cmsFloat32Number) (In[i] / 65535.0);
 881 
 882     // Get the K across Tone curve
 883     LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]);
 884 
 885     // If going across black only, keep black only
 886     if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 887 
 888         Out[0] = Out[1] = Out[2] = 0;
 889         Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0);
 890         return TRUE;
 891     }
 892 
 893     // Try the original transform,
 894     cmsPipelineEvalFloat( Inf, Outf, bp ->cmyk2cmyk);
 895 
 896     // Store a copy of the floating point result into 16-bit
 897     for (i=0; i < 4; i++)
 898             Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0);
 899 
 900     // Maybe K is already ok (mostly on K=0)
 901     if ( fabs(Outf[3] - LabK[3]) < (3.0 / 65535.0) ) {
 902         return TRUE;
 903     }
 904 
 905     // K differ, mesure and keep Lab measurement for further usage
 906     // this is done in relative colorimetric intent
 907     cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);
 908 
 909     // Is not black only and the transform doesn't keep black.
 910     // Obtain the Lab of output CMYK. After that we have Lab + K
 911     cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1);
 912 
 913     // Obtain the corresponding CMY using reverse interpolation
 914     // (K is fixed in LabK[3])
 915     if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) {
 916 
 917         // Cannot find a suitable value, so use colorimetric xform
 918         // which is already stored in Out[]
 919         return TRUE;
 920     }
 921 
 922     // Make sure to pass through K (which now is fixed)
 923     Outf[3] = LabK[3];
 924 
 925     // Apply TAC if needed
 926     SumCMY   = Outf[0]  + Outf[1] + Outf[2];
 927     SumCMYK  = SumCMY + Outf[3];
 928 
 929     if (SumCMYK > bp ->MaxTAC) {
 930 
 931         Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
 932         if (Ratio < 0)
 933             Ratio = 0;
 934     }
 935     else
 936        Ratio = 1.0;
 937 
 938     Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0);     // C
 939     Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0);     // M
 940     Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0);     // Y
 941     Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0);
 942 
 943     // Estimate the error (this goes 16 bits to Lab DBL)
 944     cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
 945     Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
 946     if (Error > bp -> MaxError)




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2020 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------
  54 //
  55 
  56 #include "lcms2_internal.h"
  57 
  58 













  59 // This is the default routine for ICC-style intents. A user may decide to override it by using a plugin.
  60 // Supported intents are perceptual, relative colorimetric, saturation and ICC-absolute colorimetric
  61 static
  62 cmsPipeline* DefaultICCintents(cmsContext     ContextID,
  63                                cmsUInt32Number nProfiles,
  64                                cmsUInt32Number Intents[],
  65                                cmsHPROFILE     hProfiles[],
  66                                cmsBool         BPC[],
  67                                cmsFloat64Number AdaptationStates[],
  68                                cmsUInt32Number dwFlags);
  69 
  70 //---------------------------------------------------------------------------------
  71 
  72 // This is the entry for black-preserving K-only intents, which are non-ICC. Last profile have to be a output profile
  73 // to do the trick (no devicelinks allowed at that position)
  74 static
  75 cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,
  76                                           cmsUInt32Number nProfiles,
  77                                           cmsUInt32Number Intents[],
  78                                           cmsHPROFILE     hProfiles[],


 709 
 710         case INTENT_PRESERVE_K_ONLY_SATURATION:
 711         case INTENT_PRESERVE_K_PLANE_SATURATION:
 712             return INTENT_SATURATION;
 713 
 714         default: return Intent;
 715     }
 716 }
 717 
 718 // Sampler for Black-only preserving CMYK->CMYK transforms
 719 
 720 typedef struct {
 721     cmsPipeline*    cmyk2cmyk;      // The original transform
 722     cmsToneCurve*   KTone;          // Black-to-black tone curve
 723 
 724 } GrayOnlyParams;
 725 
 726 
 727 // Preserve black only if that is the only ink used
 728 static
 729 int BlackPreservingGrayOnlySampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
 730 {
 731     GrayOnlyParams* bp = (GrayOnlyParams*) Cargo;
 732 
 733     // If going across black only, keep black only
 734     if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 735 
 736         // TAC does not apply because it is black ink!
 737         Out[0] = Out[1] = Out[2] = 0;
 738         Out[3] = cmsEvalToneCurve16(bp->KTone, In[3]);
 739         return TRUE;
 740     }
 741 
 742     // Keep normal transform for other colors
 743     bp ->cmyk2cmyk ->Eval16Fn(In, Out, bp ->cmyk2cmyk->Data);
 744     return TRUE;
 745 }
 746 
 747 // This is the entry for black-preserving K-only intents, which are non-ICC
 748 static
 749 cmsPipeline*  BlackPreservingKOnlyIntents(cmsContext     ContextID,


 836 // K Plane-preserving CMYK to CMYK ------------------------------------------------------------------------------------
 837 
 838 typedef struct {
 839 
 840     cmsPipeline*     cmyk2cmyk;     // The original transform
 841     cmsHTRANSFORM    hProofOutput;  // Output CMYK to Lab (last profile)
 842     cmsHTRANSFORM    cmyk2Lab;      // The input chain
 843     cmsToneCurve*    KTone;         // Black-to-black tone curve
 844     cmsPipeline*     LabK2cmyk;     // The output profile
 845     cmsFloat64Number MaxError;
 846 
 847     cmsHTRANSFORM    hRoundTrip;
 848     cmsFloat64Number MaxTAC;
 849 
 850 
 851 } PreserveKPlaneParams;
 852 
 853 
 854 // The CLUT will be stored at 16 bits, but calculations are performed at cmsFloat32Number precision
 855 static
 856 int BlackPreservingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
 857 {
 858     int i;
 859     cmsFloat32Number Inf[4], Outf[4];
 860     cmsFloat32Number LabK[4];
 861     cmsFloat64Number SumCMY, SumCMYK, Error, Ratio;
 862     cmsCIELab ColorimetricLab, BlackPreservingLab;
 863     PreserveKPlaneParams* bp = (PreserveKPlaneParams*) Cargo;
 864 
 865     // Convert from 16 bits to floating point
 866     for (i=0; i < 4; i++)
 867         Inf[i] = (cmsFloat32Number) (In[i] / 65535.0);
 868 
 869     // Get the K across Tone curve
 870     LabK[3] = cmsEvalToneCurveFloat(bp ->KTone, Inf[3]);
 871 
 872     // If going across black only, keep black only
 873     if (In[0] == 0 && In[1] == 0 && In[2] == 0) {
 874 
 875         Out[0] = Out[1] = Out[2] = 0;
 876         Out[3] = _cmsQuickSaturateWord(LabK[3] * 65535.0);
 877         return TRUE;
 878     }
 879 
 880     // Try the original transform,
 881     cmsPipelineEvalFloat(Inf, Outf, bp ->cmyk2cmyk);
 882 
 883     // Store a copy of the floating point result into 16-bit
 884     for (i=0; i < 4; i++)
 885             Out[i] = _cmsQuickSaturateWord(Outf[i] * 65535.0);
 886 
 887     // Maybe K is already ok (mostly on K=0)
 888     if (fabsf(Outf[3] - LabK[3]) < (3.0 / 65535.0)) {
 889         return TRUE;
 890     }
 891 
 892     // K differ, measure and keep Lab measurement for further usage
 893     // this is done in relative colorimetric intent
 894     cmsDoTransform(bp->hProofOutput, Out, &ColorimetricLab, 1);
 895 
 896     // Is not black only and the transform doesn't keep black.
 897     // Obtain the Lab of output CMYK. After that we have Lab + K
 898     cmsDoTransform(bp ->cmyk2Lab, Outf, LabK, 1);
 899 
 900     // Obtain the corresponding CMY using reverse interpolation
 901     // (K is fixed in LabK[3])
 902     if (!cmsPipelineEvalReverseFloat(LabK, Outf, Outf, bp ->LabK2cmyk)) {
 903 
 904         // Cannot find a suitable value, so use colorimetric xform
 905         // which is already stored in Out[]
 906         return TRUE;
 907     }
 908 
 909     // Make sure to pass through K (which now is fixed)
 910     Outf[3] = LabK[3];
 911 
 912     // Apply TAC if needed
 913     SumCMY   = (cmsFloat64Number) Outf[0]  + Outf[1] + Outf[2];
 914     SumCMYK  = SumCMY + Outf[3];
 915 
 916     if (SumCMYK > bp ->MaxTAC) {
 917 
 918         Ratio = 1 - ((SumCMYK - bp->MaxTAC) / SumCMY);
 919         if (Ratio < 0)
 920             Ratio = 0;
 921     }
 922     else
 923        Ratio = 1.0;
 924 
 925     Out[0] = _cmsQuickSaturateWord(Outf[0] * Ratio * 65535.0);     // C
 926     Out[1] = _cmsQuickSaturateWord(Outf[1] * Ratio * 65535.0);     // M
 927     Out[2] = _cmsQuickSaturateWord(Outf[2] * Ratio * 65535.0);     // Y
 928     Out[3] = _cmsQuickSaturateWord(Outf[3] * 65535.0);
 929 
 930     // Estimate the error (this goes 16 bits to Lab DBL)
 931     cmsDoTransform(bp->hProofOutput, Out, &BlackPreservingLab, 1);
 932     Error = cmsDeltaE(&ColorimetricLab, &BlackPreservingLab);
 933     if (Error > bp -> MaxError)


< prev index next >