< prev index next >

src/java.desktop/share/native/liblcms/cmsgamma.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-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 }
< prev index next >