< prev index next >

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

Print this page

 418 }
 419 
 420 // This is a devicelink operating in CMYK for ink-limiting
 421 
 422 cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
 423                                                      cmsColorSpaceSignature ColorSpace,
 424                                                      cmsFloat64Number Limit)
 425 {
 426     cmsHPROFILE hICC;
 427     cmsPipeline* LUT;
 428     cmsStage* CLUT;
 429     cmsInt32Number nChannels;
 430 
 431     if (ColorSpace != cmsSigCmykData) {
 432         cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
 433         return NULL;
 434     }
 435 
 436     if (Limit < 0.0 || Limit > 400) {
 437 
 438         cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 0..400");
 439         if (Limit < 0) Limit = 0;
 440         if (Limit > 400) Limit = 400;
 441 
 442     }
 443 
 444     hICC = cmsCreateProfilePlaceholder(ContextID);
 445     if (!hICC)                          // can't allocate
 446         return NULL;
 447 
 448     cmsSetProfileVersion(hICC, 4.4);
 449 
 450     cmsSetDeviceClass(hICC,      cmsSigLinkClass);
 451     cmsSetColorSpace(hICC,       ColorSpace);
 452     cmsSetPCS(hICC,              ColorSpace);
 453 
 454     cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 455 
 456 
 457     // Creates a Pipeline with 3D grid only
 458     LUT = cmsPipelineAlloc(ContextID, 4, 4);
 459     if (LUT == NULL) goto Error;
 460 
 461 

 684        Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
 685        if (Gamma22[0] == NULL) return NULL;
 686 
 687        hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22);
 688        cmsFreeToneCurve(Gamma22[0]);
 689        if (hsRGB == NULL) return NULL;
 690 
 691        if (!SetTextTags(hsRGB, L"sRGB built-in")) {
 692            cmsCloseProfile(hsRGB);
 693            return NULL;
 694        }
 695 
 696        return hsRGB;
 697 }
 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;

1043     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
1044     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType   } },
1045     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  5,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
1046     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  1,  { cmsSigCurveSetElemType }},
1047     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
1048     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }},
1049     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  5,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }}
1050 };
1051 
1052 #define SIZE_OF_ALLOWED_LUT (sizeof(AllowedLUTTypes)/sizeof(cmsAllowedLUT))
1053 
1054 // Check a single entry
1055 static
1056 cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut)
1057 {
1058     cmsStage* mpe;
1059     int n;
1060 
1061     for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) {
1062 
1063         if (n > Tab ->nTypes) return FALSE;
1064         if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
1065     }
1066 
1067     return (n == Tab ->nTypes);
1068 }
1069 
1070 
1071 static
1072 const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTagSignature DestinationTag)
1073 {
1074     cmsUInt32Number n;
1075 
1076     for (n=0; n < SIZE_OF_ALLOWED_LUT; n++) {
1077 
1078         const cmsAllowedLUT* Tab = AllowedLUTTypes + n;
1079 
1080         if (IsV4 ^ Tab -> IsV4) continue;
1081         if ((Tab ->RequiredTag != 0) && (Tab ->RequiredTag != DestinationTag)) continue;
1082 
1083         if (CheckOne(Tab, Lut)) return Tab;
1084     }
1085 
1086     return NULL;
1087 }
1088 
1089 
1090 // Does convert a transform into a device link profile
1091 cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
1092 {
1093     cmsHPROFILE hProfile = NULL;
1094         cmsUInt32Number FrmIn, FrmOut;
1095         cmsInt32Number ChansIn, ChansOut;
1096         int ColorSpaceBitsIn, ColorSpaceBitsOut;
1097     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1098     cmsPipeline* LUT = NULL;
1099     cmsStage* mpe;
1100     cmsContext ContextID = cmsGetTransformContextID(hTransform);
1101     const cmsAllowedLUT* AllowedLUT;
1102     cmsTagSignature DestinationTag;
1103     cmsProfileClassSignature deviceClass;
1104 
1105     _cmsAssert(hTransform != NULL);
1106 



1107     // Get the first mpe to check for named color
1108     mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);
1109 
1110     // Check if is a named color transform
1111     if (mpe != NULL) {
1112 
1113         if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
1114             return CreateNamedColorDevicelink(hTransform);
1115         }
1116     }
1117 
1118     // First thing to do is to get a copy of the transformation
1119     LUT = cmsPipelineDup(xform ->Lut);
1120     if (LUT == NULL) return NULL;
1121 
1122     // Time to fix the Lab2/Lab4 issue.
1123     if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
1124 
1125         if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
1126             goto Error;

 418 }
 419 
 420 // This is a devicelink operating in CMYK for ink-limiting
 421 
 422 cmsHPROFILE CMSEXPORT cmsCreateInkLimitingDeviceLinkTHR(cmsContext ContextID,
 423                                                      cmsColorSpaceSignature ColorSpace,
 424                                                      cmsFloat64Number Limit)
 425 {
 426     cmsHPROFILE hICC;
 427     cmsPipeline* LUT;
 428     cmsStage* CLUT;
 429     cmsInt32Number nChannels;
 430 
 431     if (ColorSpace != cmsSigCmykData) {
 432         cmsSignalError(ContextID, cmsERROR_COLORSPACE_CHECK, "InkLimiting: Only CMYK currently supported");
 433         return NULL;
 434     }
 435 
 436     if (Limit < 0.0 || Limit > 400) {
 437 
 438         cmsSignalError(ContextID, cmsERROR_RANGE, "InkLimiting: Limit should be between 1..400");
 439         if (Limit < 1) Limit = 1;
 440         if (Limit > 400) Limit = 400;

 441     }
 442 
 443     hICC = cmsCreateProfilePlaceholder(ContextID);
 444     if (!hICC)                          // can't allocate
 445         return NULL;
 446 
 447     cmsSetProfileVersion(hICC, 4.4);
 448 
 449     cmsSetDeviceClass(hICC,      cmsSigLinkClass);
 450     cmsSetColorSpace(hICC,       ColorSpace);
 451     cmsSetPCS(hICC,              ColorSpace);
 452 
 453     cmsSetHeaderRenderingIntent(hICC,  INTENT_PERCEPTUAL);
 454 
 455 
 456     // Creates a Pipeline with 3D grid only
 457     LUT = cmsPipelineAlloc(ContextID, 4, 4);
 458     if (LUT == NULL) goto Error;
 459 
 460 

 683        Gamma22[0] = Gamma22[1] = Gamma22[2] = Build_sRGBGamma(ContextID);
 684        if (Gamma22[0] == NULL) return NULL;
 685 
 686        hsRGB = cmsCreateRGBProfileTHR(ContextID, &D65, &Rec709Primaries, Gamma22);
 687        cmsFreeToneCurve(Gamma22[0]);
 688        if (hsRGB == NULL) return NULL;
 689 
 690        if (!SetTextTags(hsRGB, L"sRGB built-in")) {
 691            cmsCloseProfile(hsRGB);
 692            return NULL;
 693        }
 694 
 695        return hsRGB;
 696 }
 697 
 698 cmsHPROFILE CMSEXPORT cmsCreate_sRGBProfile(void)
 699 {
 700     return cmsCreate_sRGBProfileTHR(NULL);
 701 }
 702 
 703 /**
 704 * Oklab colorspace profile (experimental)
 705 *
 706 * This virtual profile cannot be saved as an ICC file
 707 */
 708 cmsHPROFILE cmsCreate_OkLabProfile(cmsContext ctx)
 709 {
 710     cmsStage* XYZPCS = _cmsStageNormalizeFromXyzFloat(ctx);
 711     cmsStage* PCSXYZ = _cmsStageNormalizeToXyzFloat(ctx);
 712 
 713     const double M_D65_D50[] =
 714     {
 715        1.047886, 0.022919, -0.050216,
 716        0.029582, 0.990484, -0.017079,
 717       -0.009252, 0.015073,  0.751678
 718     };
 719 
 720     const double M_D50_D65[] =
 721     {
 722          0.955512609517083, -0.023073214184645,  0.063308961782107,
 723         -0.028324949364887,  1.009942432477107,  0.021054814890112,
 724          0.012328875695483, -0.020535835374141,  1.330713916450354
 725     };
 726 
 727     cmsStage* D65toD50 = cmsStageAllocMatrix(ctx, 3, 3, M_D65_D50, NULL);
 728     cmsStage* D50toD65 = cmsStageAllocMatrix(ctx, 3, 3, M_D50_D65, NULL);
 729 
 730     const double M_D65_LMS[] =
 731     {
 732         0.8189330101, 0.3618667424, -0.1288597137,
 733         0.0329845436, 0.9293118715,  0.0361456387,
 734         0.0482003018, 0.2643662691,  0.6338517070
 735     };
 736 
 737     const double M_LMS_D65[] =
 738     {
 739         1.227013851103521, -0.557799980651822,  0.281256148966468,
 740        -0.040580178423281,  1.112256869616830, -0.071676678665601,
 741        -0.076381284505707, -0.421481978418013,  1.586163220440795
 742     };
 743 
 744     cmsStage* D65toLMS = cmsStageAllocMatrix(ctx, 3, 3, M_D65_LMS, NULL);
 745     cmsStage* LMStoD65 = cmsStageAllocMatrix(ctx, 3, 3, M_LMS_D65, NULL);
 746 
 747     cmsToneCurve* CubeRoot = cmsBuildGamma(ctx, 1.0 / 3.0);
 748     cmsToneCurve* Cube     = cmsBuildGamma(ctx,  3.0);
 749 
 750     cmsToneCurve* Roots[3] = { CubeRoot, CubeRoot, CubeRoot };
 751     cmsToneCurve* Cubes[3] = { Cube, Cube, Cube };
 752 
 753     cmsStage* NonLinearityFw = cmsStageAllocToneCurves(ctx, 3, Roots);
 754     cmsStage* NonLinearityRv = cmsStageAllocToneCurves(ctx, 3, Cubes);
 755 
 756     const double M_LMSprime_OkLab[] =
 757     {
 758         0.2104542553,  0.7936177850, -0.0040720468,
 759         1.9779984951, -2.4285922050,  0.4505937099,
 760         0.0259040371,  0.7827717662, -0.8086757660
 761     };
 762 
 763     const double M_OkLab_LMSprime[] =
 764     {
 765         0.999999998450520,  0.396337792173768,  0.215803758060759,
 766         1.000000008881761, -0.105561342323656, -0.063854174771706,
 767         1.000000054672411, -0.089484182094966, -1.291485537864092
 768     };
 769 
 770     cmsStage* LMSprime_OkLab = cmsStageAllocMatrix(ctx, 3, 3, M_LMSprime_OkLab, NULL);
 771     cmsStage* OkLab_LMSprime = cmsStageAllocMatrix(ctx, 3, 3, M_OkLab_LMSprime, NULL);
 772 
 773     cmsPipeline* AToB = cmsPipelineAlloc(ctx, 3, 3);
 774     cmsPipeline* BToA = cmsPipelineAlloc(ctx, 3, 3);
 775 
 776     cmsHPROFILE hProfile = cmsCreateProfilePlaceholder(ctx);
 777 
 778     cmsSetProfileVersion(hProfile, 4.4);
 779 
 780     cmsSetDeviceClass(hProfile, cmsSigColorSpaceClass);
 781     cmsSetColorSpace(hProfile, cmsSig3colorData);
 782     cmsSetPCS(hProfile, cmsSigXYZData);
 783 
 784     cmsSetHeaderRenderingIntent(hProfile, INTENT_RELATIVE_COLORIMETRIC);
 785 
 786     /**
 787     * Conversion PCS (XYZ/D50) to OkLab
 788     */
 789     if (!cmsPipelineInsertStage(BToA, cmsAT_END, PCSXYZ)) goto error;
 790     if (!cmsPipelineInsertStage(BToA, cmsAT_END, D50toD65)) goto error;
 791     if (!cmsPipelineInsertStage(BToA, cmsAT_END, D65toLMS)) goto error;
 792     if (!cmsPipelineInsertStage(BToA, cmsAT_END, NonLinearityFw)) goto error;
 793     if (!cmsPipelineInsertStage(BToA, cmsAT_END, LMSprime_OkLab)) goto error;
 794 
 795     if (!cmsWriteTag(hProfile, cmsSigBToA0Tag, BToA)) goto error;
 796 
 797     if (!cmsPipelineInsertStage(AToB, cmsAT_END, OkLab_LMSprime)) goto error;
 798     if (!cmsPipelineInsertStage(AToB, cmsAT_END, NonLinearityRv)) goto error;
 799     if (!cmsPipelineInsertStage(AToB, cmsAT_END, LMStoD65)) goto error;
 800     if (!cmsPipelineInsertStage(AToB, cmsAT_END, D65toD50)) goto error;
 801     if (!cmsPipelineInsertStage(AToB, cmsAT_END, XYZPCS)) goto error;
 802 
 803     if (!cmsWriteTag(hProfile, cmsSigAToB0Tag, AToB)) goto error;
 804 
 805     cmsPipelineFree(BToA);
 806     cmsPipelineFree(AToB);
 807 
 808     cmsFreeToneCurve(CubeRoot);
 809     cmsFreeToneCurve(Cube);
 810 
 811     return hProfile;
 812 
 813 error:
 814     cmsPipelineFree(BToA);
 815     cmsPipelineFree(AToB);
 816 
 817     cmsFreeToneCurve(CubeRoot);
 818     cmsFreeToneCurve(Cube);
 819     cmsCloseProfile(hProfile);
 820 
 821     return NULL;
 822 
 823 }
 824 
 825 
 826 typedef struct {
 827                 cmsFloat64Number Brightness;
 828                 cmsFloat64Number Contrast;
 829                 cmsFloat64Number Hue;
 830                 cmsFloat64Number Saturation;
 831                 cmsBool          lAdjustWP;
 832                 cmsCIEXYZ WPsrc, WPdest;
 833 
 834 } BCHSWADJUSTS, *LPBCHSWADJUSTS;
 835 
 836 
 837 static
 838 int bchswSampler(CMSREGISTER const cmsUInt16Number In[], CMSREGISTER cmsUInt16Number Out[], CMSREGISTER void* Cargo)
 839 {
 840     cmsCIELab LabIn, LabOut;
 841     cmsCIELCh LChIn, LChOut;
 842     cmsCIEXYZ XYZ;
 843     LPBCHSWADJUSTS bchsw = (LPBCHSWADJUSTS) Cargo;

1163     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType } },
1164     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType   } },
1165     { TRUE , cmsSigAToB0Tag, cmsSigLutAtoBType,  5,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
1166     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  1,  { cmsSigCurveSetElemType }},
1167     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType }},
1168     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  3,  { cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }},
1169     { TRUE , cmsSigBToA0Tag, cmsSigLutBtoAType,  5,  { cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType }}
1170 };
1171 
1172 #define SIZE_OF_ALLOWED_LUT (sizeof(AllowedLUTTypes)/sizeof(cmsAllowedLUT))
1173 
1174 // Check a single entry
1175 static
1176 cmsBool CheckOne(const cmsAllowedLUT* Tab, const cmsPipeline* Lut)
1177 {
1178     cmsStage* mpe;
1179     int n;
1180 
1181     for (n=0, mpe = Lut ->Elements; mpe != NULL; mpe = mpe ->Next, n++) {
1182 
1183         if (n >= Tab ->nTypes) return FALSE;
1184         if (cmsStageType(mpe) != Tab ->MpeTypes[n]) return FALSE;
1185     }
1186 
1187     return (n == Tab ->nTypes);
1188 }
1189 
1190 
1191 static
1192 const cmsAllowedLUT* FindCombination(const cmsPipeline* Lut, cmsBool IsV4, cmsTagSignature DestinationTag)
1193 {
1194     cmsUInt32Number n;
1195 
1196     for (n=0; n < SIZE_OF_ALLOWED_LUT; n++) {
1197 
1198         const cmsAllowedLUT* Tab = AllowedLUTTypes + n;
1199 
1200         if (IsV4 ^ Tab -> IsV4) continue;
1201         if ((Tab ->RequiredTag != 0) && (Tab ->RequiredTag != DestinationTag)) continue;
1202 
1203         if (CheckOne(Tab, Lut)) return Tab;
1204     }
1205 
1206     return NULL;
1207 }
1208 
1209 
1210 // Does convert a transform into a device link profile
1211 cmsHPROFILE CMSEXPORT cmsTransform2DeviceLink(cmsHTRANSFORM hTransform, cmsFloat64Number Version, cmsUInt32Number dwFlags)
1212 {
1213     cmsHPROFILE hProfile = NULL;
1214     cmsUInt32Number FrmIn, FrmOut;
1215     cmsInt32Number ChansIn, ChansOut;
1216     int ColorSpaceBitsIn, ColorSpaceBitsOut;
1217     _cmsTRANSFORM* xform = (_cmsTRANSFORM*) hTransform;
1218     cmsPipeline* LUT = NULL;
1219     cmsStage* mpe;
1220     cmsContext ContextID = cmsGetTransformContextID(hTransform);
1221     const cmsAllowedLUT* AllowedLUT;
1222     cmsTagSignature DestinationTag;
1223     cmsProfileClassSignature deviceClass;
1224 
1225     _cmsAssert(hTransform != NULL);
1226 
1227     // Check if the pipeline holding is valid
1228     if (xform -> Lut == NULL) return NULL;
1229 
1230     // Get the first mpe to check for named color
1231     mpe = cmsPipelineGetPtrToFirstStage(xform ->Lut);
1232 
1233     // Check if is a named color transform
1234     if (mpe != NULL) {
1235 
1236         if (cmsStageType(mpe) == cmsSigNamedColorElemType) {
1237             return CreateNamedColorDevicelink(hTransform);
1238         }
1239     }
1240 
1241     // First thing to do is to get a copy of the transformation
1242     LUT = cmsPipelineDup(xform ->Lut);
1243     if (LUT == NULL) return NULL;
1244 
1245     // Time to fix the Lab2/Lab4 issue.
1246     if ((xform ->EntryColorSpace == cmsSigLabData) && (Version < 4.0)) {
1247 
1248         if (!cmsPipelineInsertStage(LUT, cmsAT_BEGIN, _cmsStageAllocLabV2ToV4curves(ContextID)))
1249             goto Error;
< prev index next >