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 //---------------------------------------------------------------------------------
373 }
374
375 // Ink-limiting algorithm
376 //
377 // Sum = C + M + Y + K
378 // If Sum > InkLimit
379 // Ratio= 1 - (Sum - InkLimit) / (C + M + Y)
380 // if Ratio <0
381 // Ratio=0
382 // endif
383 // Else
384 // Ratio=1
385 // endif
386 //
387 // C = Ratio * C
388 // M = Ratio * M
389 // Y = Ratio * Y
390 // K: Does not change
391
392 static
393 int InkLimitingSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
394 {
395 cmsFloat64Number InkLimit = *(cmsFloat64Number *) Cargo;
396 cmsFloat64Number SumCMY, SumCMYK, Ratio;
397
398 InkLimit = (InkLimit * 655.35);
399
400 SumCMY = In[0] + In[1] + In[2];
401 SumCMYK = SumCMY + In[3];
402
403 if (SumCMYK > InkLimit) {
404
405 Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY);
406 if (Ratio < 0)
407 Ratio = 0;
408 }
409 else Ratio = 1;
410
411 Out[0] = _cmsQuickSaturateWord(In[0] * Ratio); // C
412 Out[1] = _cmsQuickSaturateWord(In[1] * Ratio); // M
413 Out[2] = _cmsQuickSaturateWord(In[2] * Ratio); // Y
624 Error:
625
626 if (LUT != NULL)
627 cmsPipelineFree(LUT);
628
629 if (hProfile != NULL)
630 cmsCloseProfile(hProfile);
631
632 return NULL;
633 }
634
635
636 cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void)
637 {
638 return cmsCreateXYZProfileTHR(NULL);
639 }
640
641
642 //sRGB Curves are defined by:
643 //
644 //If R’sRGB,G’sRGB, B’sRGB < 0.04045
645 //
646 // R = R’sRGB / 12.92
647 // G = G’sRGB / 12.92
648 // B = B’sRGB / 12.92
649 //
650 //
651 //else if R’sRGB,G’sRGB, B’sRGB >= 0.04045
652 //
653 // R = ((R’sRGB + 0.055) / 1.055)^2.4
654 // G = ((G’sRGB + 0.055) / 1.055)^2.4
655 // B = ((B’sRGB + 0.055) / 1.055)^2.4
656
657 static
658 cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
659 {
660 cmsFloat64Number Parameters[5];
661
662 Parameters[0] = 2.4;
663 Parameters[1] = 1. / 1.055;
664 Parameters[2] = 0.055 / 1.055;
665 Parameters[3] = 1. / 12.92;
666 Parameters[4] = 0.04045;
667
668 return cmsBuildParametricToneCurve(ContextID, 4, Parameters);
669 }
670
671 // Create the ICC virtual profile for sRGB space
672 cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
673 {
674 cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
675 cmsCIExyYTRIPLE Rec709Primaries = {
698
699 cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
700 {
701 return cmsCreate_sRGBProfileTHR(NULL);
702 }
703
704
705
706 typedef struct {
707 cmsFloat64Number Brightness;
708 cmsFloat64Number Contrast;
709 cmsFloat64Number Hue;
710 cmsFloat64Number Saturation;
711 cmsBool lAdjustWP;
712 cmsCIEXYZ WPsrc, WPdest;
713
714 } BCHSWADJUSTS, *LPBCHSWADJUSTS;
715
716
717 static
718 int bchswSampler(register const cmsUInt16Number In[], register cmsUInt16Number Out[], register void* Cargo)
719 {
720 cmsCIELab LabIn, LabOut;
721 cmsCIELCh LChIn, LChOut;
722 cmsCIEXYZ XYZ;
723 LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;
724
725
726 cmsLabEncoded2Float(&LabIn, In);
727
728
729 cmsLab2LCh(&LChIn, &LabIn);
730
731 // Do some adjusts on LCh
732
733 LChOut.L = LChIn.L * bchsw ->Contrast + bchsw ->Brightness;
734 LChOut.C = LChIn.C + bchsw -> Saturation;
735 LChOut.h = LChIn.h + bchsw -> Hue;
736
737
738 cmsLCh2Lab(&LabOut, &LChOut);
1108
1109 // Check if is a named color transform
1110 if (mpe != NULL) {
1111
1112 if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
1113 return CreateNamedColorDevicelink(hTransform);
1114 }
1115 }
1116
1117 // First thing to do is to get a copy of the transformation
1118 LUT = cmsPipelineDup(xform ->Lut);
1119 if (LUT == NULL) return NULL;
1120
1121 // Time to fix the Lab2/Lab4 issue.
1122 if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
1123
1124 if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
1125 goto Error;
1126 }
1127
1128 // On the output side too
1129 if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
1130
1131 if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
1132 goto Error;
1133 }
1134
1135
1136 hProfile = cmsCreateProfilePlaceholder(ContextID);
1137 if (!hProfile) goto Error; // can't allocate
1138
1139 cmsSetProfileVersion(hProfile, Version);
1140
1141 FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);
1142
1143 // Optimize the LUT and precalculate a devicelink
1144
1145 ChansIn = cmsChannelsOf(xform -> EntryColorSpace);
1146 ChansOut = cmsChannelsOf(xform -> ExitColorSpace);
1147
1148 ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace);
1149 ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);
1150
|
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 //---------------------------------------------------------------------------------
373 }
374
375 // Ink-limiting algorithm
376 //
377 // Sum = C + M + Y + K
378 // If Sum > InkLimit
379 // Ratio= 1 - (Sum - InkLimit) / (C + M + Y)
380 // if Ratio <0
381 // Ratio=0
382 // endif
383 // Else
384 // Ratio=1
385 // endif
386 //
387 // C = Ratio * C
388 // M = Ratio * M
389 // Y = Ratio * Y
390 // K: Does not change
391
392 static
393 int InkLimitingSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
394 {
395 cmsFloat64Number InkLimit = *(cmsFloat64Number *) Cargo;
396 cmsFloat64Number SumCMY, SumCMYK, Ratio;
397
398 InkLimit = (InkLimit * 655.35);
399
400 SumCMY = In[0] + In[1] + In[2];
401 SumCMYK = SumCMY + In[3];
402
403 if (SumCMYK > InkLimit) {
404
405 Ratio = 1 - ((SumCMYK - InkLimit) / SumCMY);
406 if (Ratio < 0)
407 Ratio = 0;
408 }
409 else Ratio = 1;
410
411 Out[0] = _cmsQuickSaturateWord(In[0] * Ratio); // C
412 Out[1] = _cmsQuickSaturateWord(In[1] * Ratio); // M
413 Out[2] = _cmsQuickSaturateWord(In[2] * Ratio); // Y
624 Error:
625
626 if (LUT != NULL)
627 cmsPipelineFree(LUT);
628
629 if (hProfile != NULL)
630 cmsCloseProfile(hProfile);
631
632 return NULL;
633 }
634
635
636 cmsHPROFILE CMSEXPORT cmsCreateXYZProfile(void)
637 {
638 return cmsCreateXYZProfileTHR(NULL);
639 }
640
641
642 //sRGB Curves are defined by:
643 //
644 //If R'sRGB,G'sRGB, B'sRGB < 0.04045
645 //
646 // R = R'sRGB / 12.92
647 // G = G'sRGB / 12.92
648 // B = B'sRGB / 12.92
649 //
650 //
651 //else if R'sRGB,G'sRGB, B'sRGB >= 0.04045
652 //
653 // R = ((R'sRGB + 0.055) / 1.055)^2.4
654 // G = ((G'sRGB + 0.055) / 1.055)^2.4
655 // B = ((B'sRGB + 0.055) / 1.055)^2.4
656
657 static
658 cmsToneCurve* Build_sRGBGamma(cmsContext ContextID)
659 {
660 cmsFloat64Number Parameters[5];
661
662 Parameters[0] = 2.4;
663 Parameters[1] = 1. / 1.055;
664 Parameters[2] = 0.055 / 1.055;
665 Parameters[3] = 1. / 12.92;
666 Parameters[4] = 0.04045;
667
668 return cmsBuildParametricToneCurve(ContextID, 4, Parameters);
669 }
670
671 // Create the ICC virtual profile for sRGB space
672 cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfileTHR(cmsContext ContextID)
673 {
674 cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
675 cmsCIExyYTRIPLE Rec709Primaries = {
698
699 cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
700 {
701 return cmsCreate_sRGBProfileTHR(NULL);
702 }
703
704
705
706 typedef struct {
707 cmsFloat64Number Brightness;
708 cmsFloat64Number Contrast;
709 cmsFloat64Number Hue;
710 cmsFloat64Number Saturation;
711 cmsBool lAdjustWP;
712 cmsCIEXYZ WPsrc, WPdest;
713
714 } BCHSWADJUSTS, *LPBCHSWADJUSTS;
715
716
717 static
718 int bchswSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
719 {
720 cmsCIELab LabIn, LabOut;
721 cmsCIELCh LChIn, LChOut;
722 cmsCIEXYZ XYZ;
723 LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;
724
725
726 cmsLabEncoded2Float(&LabIn, In);
727
728
729 cmsLab2LCh(&LChIn, &LabIn);
730
731 // Do some adjusts on LCh
732
733 LChOut.L = LChIn.L * bchsw ->Contrast + bchsw ->Brightness;
734 LChOut.C = LChIn.C + bchsw -> Saturation;
735 LChOut.h = LChIn.h + bchsw -> Hue;
736
737
738 cmsLCh2Lab(&LabOut, &LChOut);
1108
1109 // Check if is a named color transform
1110 if (mpe != NULL) {
1111
1112 if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
1113 return CreateNamedColorDevicelink(hTransform);
1114 }
1115 }
1116
1117 // First thing to do is to get a copy of the transformation
1118 LUT = cmsPipelineDup(xform ->Lut);
1119 if (LUT == NULL) return NULL;
1120
1121 // Time to fix the Lab2/Lab4 issue.
1122 if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
1123
1124 if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
1125 goto Error;
1126 }
1127
1128 // On the output side too. Note that due to V2/V4 PCS encoding on lab we cannot fix white misalignments
1129 if ((xform ->ExitColorSpace) == cmsSigLabData && (Version < 4.0)) {
1130
1131 dwFlags |= cmsFLAGS_NOWHITEONWHITEFIXUP;
1132 if (!cmsPipelineInsertStage(LUT, cmsAT_END, _cmsStageAllocLabV4ToV2(ContextID)))
1133 goto Error;
1134 }
1135
1136
1137 hProfile = cmsCreateProfilePlaceholder(ContextID);
1138 if (!hProfile) goto Error; // can't allocate
1139
1140 cmsSetProfileVersion(hProfile, Version);
1141
1142 FixColorSpaces(hProfile, xform -> EntryColorSpace, xform -> ExitColorSpace, dwFlags);
1143
1144 // Optimize the LUT and precalculate a devicelink
1145
1146 ChansIn = cmsChannelsOf(xform -> EntryColorSpace);
1147 ChansOut = cmsChannelsOf(xform -> ExitColorSpace);
1148
1149 ColorSpaceBitsIn = _cmsLCMScolorSpace(xform -> EntryColorSpace);
1150 ColorSpaceBitsOut = _cmsLCMScolorSpace(xform -> ExitColorSpace);
1151
|