967 cmsFloat32Number Out[],
968 const cmsStage *mpe)
969 {
970 cmsCIELab Lab;
971 cmsCIEXYZ XYZ;
972 const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
973
974 // V4 rules
975 Lab.L = In[0] * 100.0;
976 Lab.a = In[1] * 255.0 - 128.0;
977 Lab.b = In[2] * 255.0 - 128.0;
978
979 cmsLab2XYZ(NULL, &XYZ, &Lab);
980
981 // From XYZ, range 0..19997 to 0..1.0, note that 1.99997 comes from 0xffff
982 // encoded as 1.15 fixed point, so 1 + (32767.0 / 32768.0)
983
984 Out[0] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.X / XYZadj);
985 Out[1] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Y / XYZadj);
986 Out[2] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Z / XYZadj);
987 return;
988
989 cmsUNUSED_PARAMETER(mpe);
990 }
991
992
993 // No dup or free routines needed, as the structure has no pointers in it.
994 cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID)
995 {
996 return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL);
997 }
998
999 // ********************************************************************************
1000
1001 // v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable
1002 // number of gridpoints that would make exact match. However, a prelinearization
1003 // of 258 entries, would map 0xFF00 exactly on entry 257, and this is good to avoid scum dot.
1004 // Almost all what we need but unfortunately, the rest of entries should be scaled by
1005 // (255*257/256) and this is not exact.
1006
1007 cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
1008 {
1009 cmsStage* mpe;
1179 static
1180 void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
1181 {
1182 cmsCIELab Lab;
1183 cmsCIEXYZ XYZ;
1184 const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
1185
1186 // From 0..1.0 to XYZ
1187
1188 XYZ.X = In[0] * XYZadj;
1189 XYZ.Y = In[1] * XYZadj;
1190 XYZ.Z = In[2] * XYZadj;
1191
1192 cmsXYZ2Lab(NULL, &Lab, &XYZ);
1193
1194 // From V4 Lab to 0..1.0
1195
1196 Out[0] = (cmsFloat32Number) (Lab.L / 100.0);
1197 Out[1] = (cmsFloat32Number) ((Lab.a + 128.0) / 255.0);
1198 Out[2] = (cmsFloat32Number) ((Lab.b + 128.0) / 255.0);
1199 return;
1200
1201 cmsUNUSED_PARAMETER(mpe);
1202 }
1203
1204 cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID)
1205 {
1206 return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL);
1207
1208 }
1209
1210 // ********************************************************************************
1211
1212 // For v4, S-Shaped curves are placed in a/b axis to increase resolution near gray
1213
1214 cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID)
1215 {
1216 cmsToneCurve* LabTable[3];
1217 cmsFloat64Number Params[1] = {2.4} ;
1218
1219 LabTable[0] = cmsBuildGamma(ContextID, 1.0);
1220 LabTable[1] = cmsBuildParametricToneCurve(ContextID, 108, Params);
1221 LabTable[2] = cmsBuildParametricToneCurve(ContextID, 108, Params);
|
967 cmsFloat32Number Out[],
968 const cmsStage *mpe)
969 {
970 cmsCIELab Lab;
971 cmsCIEXYZ XYZ;
972 const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
973
974 // V4 rules
975 Lab.L = In[0] * 100.0;
976 Lab.a = In[1] * 255.0 - 128.0;
977 Lab.b = In[2] * 255.0 - 128.0;
978
979 cmsLab2XYZ(NULL, &XYZ, &Lab);
980
981 // From XYZ, range 0..19997 to 0..1.0, note that 1.99997 comes from 0xffff
982 // encoded as 1.15 fixed point, so 1 + (32767.0 / 32768.0)
983
984 Out[0] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.X / XYZadj);
985 Out[1] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Y / XYZadj);
986 Out[2] = (cmsFloat32Number) ((cmsFloat64Number) XYZ.Z / XYZadj);
987
988 cmsUNUSED_PARAMETER(mpe);
989
990 return;
991
992 }
993
994
995 // No dup or free routines needed, as the structure has no pointers in it.
996 cmsStage* _cmsStageAllocLab2XYZ(cmsContext ContextID)
997 {
998 return _cmsStageAllocPlaceholder(ContextID, cmsSigLab2XYZElemType, 3, 3, EvaluateLab2XYZ, NULL, NULL, NULL);
999 }
1000
1001 // ********************************************************************************
1002
1003 // v2 L=100 is supposed to be placed on 0xFF00. There is no reasonable
1004 // number of gridpoints that would make exact match. However, a prelinearization
1005 // of 258 entries, would map 0xFF00 exactly on entry 257, and this is good to avoid scum dot.
1006 // Almost all what we need but unfortunately, the rest of entries should be scaled by
1007 // (255*257/256) and this is not exact.
1008
1009 cmsStage* _cmsStageAllocLabV2ToV4curves(cmsContext ContextID)
1010 {
1011 cmsStage* mpe;
1181 static
1182 void EvaluateXYZ2Lab(const cmsFloat32Number In[], cmsFloat32Number Out[], const cmsStage *mpe)
1183 {
1184 cmsCIELab Lab;
1185 cmsCIEXYZ XYZ;
1186 const cmsFloat64Number XYZadj = MAX_ENCODEABLE_XYZ;
1187
1188 // From 0..1.0 to XYZ
1189
1190 XYZ.X = In[0] * XYZadj;
1191 XYZ.Y = In[1] * XYZadj;
1192 XYZ.Z = In[2] * XYZadj;
1193
1194 cmsXYZ2Lab(NULL, &Lab, &XYZ);
1195
1196 // From V4 Lab to 0..1.0
1197
1198 Out[0] = (cmsFloat32Number) (Lab.L / 100.0);
1199 Out[1] = (cmsFloat32Number) ((Lab.a + 128.0) / 255.0);
1200 Out[2] = (cmsFloat32Number) ((Lab.b + 128.0) / 255.0);
1201
1202 cmsUNUSED_PARAMETER(mpe);
1203
1204 return;
1205
1206 }
1207
1208 cmsStage* _cmsStageAllocXYZ2Lab(cmsContext ContextID)
1209 {
1210 return _cmsStageAllocPlaceholder(ContextID, cmsSigXYZ2LabElemType, 3, 3, EvaluateXYZ2Lab, NULL, NULL, NULL);
1211
1212 }
1213
1214 // ********************************************************************************
1215
1216 // For v4, S-Shaped curves are placed in a/b axis to increase resolution near gray
1217
1218 cmsStage* _cmsStageAllocLabPrelin(cmsContext ContextID)
1219 {
1220 cmsToneCurve* LabTable[3];
1221 cmsFloat64Number Params[1] = {2.4} ;
1222
1223 LabTable[0] = cmsBuildGamma(ContextID, 1.0);
1224 LabTable[1] = cmsBuildParametricToneCurve(ContextID, 108, Params);
1225 LabTable[2] = cmsBuildParametricToneCurve(ContextID, 108, Params);
|