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-2013 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 //---------------------------------------------------------------------------------
312
313 memmove(&p ->Segments[i], &Segments[i], sizeof(cmsCurveSegment));
314
315 if (Segments[i].Type == 0 && Segments[i].SampledPoints != NULL)
316 p ->Segments[i].SampledPoints = (cmsFloat32Number*) _cmsDupMem(ContextID, Segments[i].SampledPoints, sizeof(cmsFloat32Number) * Segments[i].nGridPoints);
317 else
318 p ->Segments[i].SampledPoints = NULL;
319
320
321 c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL);
322 if (c != NULL)
323 p ->Evals[i] = c ->Evaluator;
324 }
325 }
326
327 p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
328 if (p->InterpParams != NULL)
329 return p;
330
331 Error:
332 if (p -> Segments) _cmsFree(ContextID, p ->Segments);
333 if (p -> Evals) _cmsFree(ContextID, p -> Evals);
334 if (p ->Table16) _cmsFree(ContextID, p ->Table16);
335 _cmsFree(ContextID, p);
336 return NULL;
337 }
338
339
340 // Parametric Fn using floating point
341 static
342 cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R)
343 {
344 cmsFloat64Number e, Val, disc;
345
346 switch (Type) {
347
348 // X = Y ^ Gamma
349 case 1:
350 if (R < 0) {
351
352 if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE)
829
830 // Final segment is constant = lastsample
831 Seg[2].x0 = 1.0;
832 Seg[2].x1 = PLUS_INF;
833 Seg[2].Type = 6;
834
835 Seg[2].Params[0] = 1;
836 Seg[2].Params[1] = 0;
837 Seg[2].Params[2] = 0;
838 Seg[2].Params[3] = values[nEntries-1];
839 Seg[2].Params[4] = 0;
840
841
842 return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
843 }
844
845 // Parametric curves
846 //
847 // Parameters goes as: Curve, a, b, c, d, e, f
848 // Type is the ICC type +1
849 // if type is negative, then the curve is analyticaly inverted
850 cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[])
851 {
852 cmsCurveSegment Seg0;
853 int Pos = 0;
854 cmsUInt32Number size;
855 _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos);
856
857 _cmsAssert(Params != NULL);
858
859 if (c == NULL) {
860 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
861 return NULL;
862 }
863
864 memset(&Seg0, 0, sizeof(Seg0));
865
866 Seg0.x0 = MINUS_INF;
867 Seg0.x1 = PLUS_INF;
868 Seg0.Type = Type;
869
900
901 cmsUInt32Number i;
902
903 for (i=0; i < Curve ->nSegments; i++) {
904
905 if (Curve ->Segments[i].SampledPoints) {
906 _cmsFree(ContextID, Curve ->Segments[i].SampledPoints);
907 }
908
909 if (Curve ->SegInterp[i] != 0)
910 _cmsFreeInterpParams(Curve->SegInterp[i]);
911 }
912
913 _cmsFree(ContextID, Curve ->Segments);
914 _cmsFree(ContextID, Curve ->SegInterp);
915 }
916
917 if (Curve -> Evals)
918 _cmsFree(ContextID, Curve -> Evals);
919
920 if (Curve) _cmsFree(ContextID, Curve);
921 }
922
923 // Utility function, free 3 gamma tables
924 void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3])
925 {
926
927 _cmsAssert(Curve != NULL);
928
929 if (Curve[0] != NULL) cmsFreeToneCurve(Curve[0]);
930 if (Curve[1] != NULL) cmsFreeToneCurve(Curve[1]);
931 if (Curve[2] != NULL) cmsFreeToneCurve(Curve[2]);
932
933 Curve[0] = Curve[1] = Curve[2] = NULL;
934 }
935
936
937 // Duplicate a gamma table
938 cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In)
939 {
940 if (In == NULL) return NULL;
1270 if (w != NULL)
1271 _cmsFree(ContextID, w);
1272 }
1273 else // too many items in the table
1274 {
1275 cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Too many points.");
1276 SuccessStatus = FALSE;
1277 }
1278 }
1279 }
1280 else // Tab parameter or Tab->InterpParams is NULL
1281 {
1282 // Can't signal an error here since the ContextID is not known at this point
1283 SuccessStatus = FALSE;
1284 }
1285
1286 return SuccessStatus;
1287 }
1288
1289 // Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting
1290 // in a linear table. This way assures it is linear in 12 bits, which should be enought in most cases.
1291 cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve)
1292 {
1293 int i;
1294 int diff;
1295
1296 _cmsAssert(Curve != NULL);
1297
1298 for (i=0; i < (int) Curve ->nEntries; i++) {
1299
1300 diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries));
1301 if (diff > 0x0f)
1302 return FALSE;
1303 }
1304
1305 return TRUE;
1306 }
1307
1308 // Same, but for monotonicity
1309 cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t)
1310 {
1442
1443 // Avoid 7% on lower part to prevent
1444 // artifacts due to linear ramps
1445
1446 if (y > 0. && y < 1. && x > 0.07) {
1447
1448 gamma = log(y) / log(x);
1449 sum += gamma;
1450 sum2 += gamma * gamma;
1451 n++;
1452 }
1453 }
1454
1455 // Take a look on SD to see if gamma isn't exponential at all
1456 Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));
1457
1458 if (Std > Precision)
1459 return -1.0;
1460
1461 return (sum / n); // The mean
1462 }
|
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 //---------------------------------------------------------------------------------
312
313 memmove(&p ->Segments[i], &Segments[i], sizeof(cmsCurveSegment));
314
315 if (Segments[i].Type == 0 && Segments[i].SampledPoints != NULL)
316 p ->Segments[i].SampledPoints = (cmsFloat32Number*) _cmsDupMem(ContextID, Segments[i].SampledPoints, sizeof(cmsFloat32Number) * Segments[i].nGridPoints);
317 else
318 p ->Segments[i].SampledPoints = NULL;
319
320
321 c = GetParametricCurveByType(ContextID, Segments[i].Type, NULL);
322 if (c != NULL)
323 p ->Evals[i] = c ->Evaluator;
324 }
325 }
326
327 p ->InterpParams = _cmsComputeInterpParams(ContextID, p ->nEntries, 1, 1, p->Table16, CMS_LERP_FLAGS_16BITS);
328 if (p->InterpParams != NULL)
329 return p;
330
331 Error:
332 if (p -> SegInterp) _cmsFree(ContextID, p -> SegInterp);
333 if (p -> Segments) _cmsFree(ContextID, p -> Segments);
334 if (p -> Evals) _cmsFree(ContextID, p -> Evals);
335 if (p ->Table16) _cmsFree(ContextID, p ->Table16);
336 _cmsFree(ContextID, p);
337 return NULL;
338 }
339
340
341 // Parametric Fn using floating point
342 static
343 cmsFloat64Number DefaultEvalParametricFn(cmsInt32Number Type, const cmsFloat64Number Params[], cmsFloat64Number R)
344 {
345 cmsFloat64Number e, Val, disc;
346
347 switch (Type) {
348
349 // X = Y ^ Gamma
350 case 1:
351 if (R < 0) {
352
353 if (fabs(Params[0] - 1.0) < MATRIX_DET_TOLERANCE)
830
831 // Final segment is constant = lastsample
832 Seg[2].x0 = 1.0;
833 Seg[2].x1 = PLUS_INF;
834 Seg[2].Type = 6;
835
836 Seg[2].Params[0] = 1;
837 Seg[2].Params[1] = 0;
838 Seg[2].Params[2] = 0;
839 Seg[2].Params[3] = values[nEntries-1];
840 Seg[2].Params[4] = 0;
841
842
843 return cmsBuildSegmentedToneCurve(ContextID, 3, Seg);
844 }
845
846 // Parametric curves
847 //
848 // Parameters goes as: Curve, a, b, c, d, e, f
849 // Type is the ICC type +1
850 // if type is negative, then the curve is analytically inverted
851 cmsToneCurve* CMSEXPORT cmsBuildParametricToneCurve(cmsContext ContextID, cmsInt32Number Type, const cmsFloat64Number Params[])
852 {
853 cmsCurveSegment Seg0;
854 int Pos = 0;
855 cmsUInt32Number size;
856 _cmsParametricCurvesCollection* c = GetParametricCurveByType(ContextID, Type, &Pos);
857
858 _cmsAssert(Params != NULL);
859
860 if (c == NULL) {
861 cmsSignalError(ContextID, cmsERROR_UNKNOWN_EXTENSION, "Invalid parametric curve type %d", Type);
862 return NULL;
863 }
864
865 memset(&Seg0, 0, sizeof(Seg0));
866
867 Seg0.x0 = MINUS_INF;
868 Seg0.x1 = PLUS_INF;
869 Seg0.Type = Type;
870
901
902 cmsUInt32Number i;
903
904 for (i=0; i < Curve ->nSegments; i++) {
905
906 if (Curve ->Segments[i].SampledPoints) {
907 _cmsFree(ContextID, Curve ->Segments[i].SampledPoints);
908 }
909
910 if (Curve ->SegInterp[i] != 0)
911 _cmsFreeInterpParams(Curve->SegInterp[i]);
912 }
913
914 _cmsFree(ContextID, Curve ->Segments);
915 _cmsFree(ContextID, Curve ->SegInterp);
916 }
917
918 if (Curve -> Evals)
919 _cmsFree(ContextID, Curve -> Evals);
920
921 _cmsFree(ContextID, Curve);
922 }
923
924 // Utility function, free 3 gamma tables
925 void CMSEXPORT cmsFreeToneCurveTriple(cmsToneCurve* Curve[3])
926 {
927
928 _cmsAssert(Curve != NULL);
929
930 if (Curve[0] != NULL) cmsFreeToneCurve(Curve[0]);
931 if (Curve[1] != NULL) cmsFreeToneCurve(Curve[1]);
932 if (Curve[2] != NULL) cmsFreeToneCurve(Curve[2]);
933
934 Curve[0] = Curve[1] = Curve[2] = NULL;
935 }
936
937
938 // Duplicate a gamma table
939 cmsToneCurve* CMSEXPORT cmsDupToneCurve(const cmsToneCurve* In)
940 {
941 if (In == NULL) return NULL;
1271 if (w != NULL)
1272 _cmsFree(ContextID, w);
1273 }
1274 else // too many items in the table
1275 {
1276 cmsSignalError(ContextID, cmsERROR_RANGE, "cmsSmoothToneCurve: Too many points.");
1277 SuccessStatus = FALSE;
1278 }
1279 }
1280 }
1281 else // Tab parameter or Tab->InterpParams is NULL
1282 {
1283 // Can't signal an error here since the ContextID is not known at this point
1284 SuccessStatus = FALSE;
1285 }
1286
1287 return SuccessStatus;
1288 }
1289
1290 // Is a table linear? Do not use parametric since we cannot guarantee some weird parameters resulting
1291 // in a linear table. This way assures it is linear in 12 bits, which should be enough in most cases.
1292 cmsBool CMSEXPORT cmsIsToneCurveLinear(const cmsToneCurve* Curve)
1293 {
1294 int i;
1295 int diff;
1296
1297 _cmsAssert(Curve != NULL);
1298
1299 for (i=0; i < (int) Curve ->nEntries; i++) {
1300
1301 diff = abs((int) Curve->Table16[i] - (int) _cmsQuantizeVal(i, Curve ->nEntries));
1302 if (diff > 0x0f)
1303 return FALSE;
1304 }
1305
1306 return TRUE;
1307 }
1308
1309 // Same, but for monotonicity
1310 cmsBool CMSEXPORT cmsIsToneCurveMonotonic(const cmsToneCurve* t)
1311 {
1443
1444 // Avoid 7% on lower part to prevent
1445 // artifacts due to linear ramps
1446
1447 if (y > 0. && y < 1. && x > 0.07) {
1448
1449 gamma = log(y) / log(x);
1450 sum += gamma;
1451 sum2 += gamma * gamma;
1452 n++;
1453 }
1454 }
1455
1456 // Take a look on SD to see if gamma isn't exponential at all
1457 Std = sqrt((n * sum2 - sum * sum) / (n*(n-1)));
1458
1459 if (Std > Precision)
1460 return -1.0;
1461
1462 return (sum / n); // The mean
1463 }
1464
1465
1466 // Retrieve parameters on one-segment tone curves
1467
1468 cmsFloat64Number* CMSEXPORT cmsGetToneCurveParams(const cmsToneCurve* t)
1469 {
1470 _cmsAssert(t != NULL);
1471
1472 if (t->nSegments != 1) return NULL;
1473 return t->Segments[0].Params;
1474 }
|