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-2010 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 //---------------------------------------------------------------------------------
352 if (fabs(a) < 1.0E-10) {
353
354 return cmsmin(0, cmsmax(50, -c/b ));
355 }
356 else {
357
358 d = b*b - 4.0 * a * c;
359 if (d <= 0) {
360 return 0;
361 }
362 else {
363
364 double rt = (-b + sqrt(d)) / (2.0 * a);
365
366 return cmsmax(0, cmsmin(50, rt));
367 }
368 }
369
370 }
371
372 /*
373 static
374 cmsBool IsMonotonic(int n, const cmsFloat64Number Table[])
375 {
376 int i;
377 cmsFloat64Number last;
378
379 last = Table[n-1];
380
381 for (i = n-2; i >= 0; --i) {
382
383 if (Table[i] > last)
384
385 return FALSE;
386 else
387 last = Table[i];
388
389 }
390
391 return TRUE;
392 }
393 */
394
395 // Calculates the black point of a destination profile.
396 // This algorithm comes from the Adobe paper disclosing its black point compensation method.
397 cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
398 {
399 cmsColorSpaceSignature ColorSpace;
400 cmsHTRANSFORM hRoundTrip = NULL;
401 cmsCIELab InitialLab, destLab, Lab;
402 cmsFloat64Number inRamp[256], outRamp[256];
403 cmsFloat64Number MinL, MaxL;
404 cmsBool NearlyStraightMidrange = TRUE;
405 cmsFloat64Number yRamp[256];
406 cmsFloat64Number x[256], y[256];
407 cmsFloat64Number lo, hi;
408 int n, l;
409 cmsProfileClassSignature devClass;
410
411 // Make sure the device class is adequate
412 devClass = cmsGetDeviceClass(hProfile);
413 if (devClass == cmsSigLinkClass ||
498
499 inRamp[l] = Lab.L;
500 outRamp[l] = destLab.L;
501 }
502
503 // Make monotonic
504 for (l = 254; l > 0; --l) {
505 outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
506 }
507
508 // Check
509 if (! (outRamp[0] < outRamp[255])) {
510
511 cmsDeleteTransform(hRoundTrip);
512 BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
513 return FALSE;
514 }
515
516
517 // Test for mid range straight (only on relative colorimetric)
518
519 NearlyStraightMidrange = TRUE;
520 MinL = outRamp[0]; MaxL = outRamp[255];
521 if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
522
523 for (l=0; l < 256; l++) {
524
525 if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
526 (fabs(inRamp[l] - outRamp[l]) < 4.0 )))
527 NearlyStraightMidrange = FALSE;
528 }
529
530 // If the mid range is straight (as determined above) then the
531 // DestinationBlackPoint shall be the same as initialLab.
532 // Otherwise, the DestinationBlackPoint shall be determined
533 // using curve fitting.
534
535 if (NearlyStraightMidrange) {
536
537 cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
538 cmsDeleteTransform(hRoundTrip);
539 return TRUE;
540 }
541 }
542
543
544 // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
545 // with a corner and a nearly straight line to the white point.
546
547 for (l=0; l < 256; l++) {
548
549 yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
550 }
551
552 // find the black point using the least squares error quadratic curve fitting
553
554 if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
555 lo = 0.1;
556 hi = 0.5;
557 }
558 else {
559
560 // Perceptual and saturation
561 lo = 0.03;
562 hi = 0.25;
563 }
564
565 // Capture shadow points for the fitting.
566 n = 0;
567 for (l=0; l < 256; l++) {
568
569 cmsFloat64Number ff = yRamp[l];
570
571 if (ff >= lo && ff < hi) {
572 x[n] = inRamp[l];
573 y[n] = yRamp[l];
|
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-2014 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 //---------------------------------------------------------------------------------
352 if (fabs(a) < 1.0E-10) {
353
354 return cmsmin(0, cmsmax(50, -c/b ));
355 }
356 else {
357
358 d = b*b - 4.0 * a * c;
359 if (d <= 0) {
360 return 0;
361 }
362 else {
363
364 double rt = (-b + sqrt(d)) / (2.0 * a);
365
366 return cmsmax(0, cmsmin(50, rt));
367 }
368 }
369
370 }
371
372
373
374 // Calculates the black point of a destination profile.
375 // This algorithm comes from the Adobe paper disclosing its black point compensation method.
376 cmsBool CMSEXPORT cmsDetectDestinationBlackPoint(cmsCIEXYZ* BlackPoint, cmsHPROFILE hProfile, cmsUInt32Number Intent, cmsUInt32Number dwFlags)
377 {
378 cmsColorSpaceSignature ColorSpace;
379 cmsHTRANSFORM hRoundTrip = NULL;
380 cmsCIELab InitialLab, destLab, Lab;
381 cmsFloat64Number inRamp[256], outRamp[256];
382 cmsFloat64Number MinL, MaxL;
383 cmsBool NearlyStraightMidrange = TRUE;
384 cmsFloat64Number yRamp[256];
385 cmsFloat64Number x[256], y[256];
386 cmsFloat64Number lo, hi;
387 int n, l;
388 cmsProfileClassSignature devClass;
389
390 // Make sure the device class is adequate
391 devClass = cmsGetDeviceClass(hProfile);
392 if (devClass == cmsSigLinkClass ||
477
478 inRamp[l] = Lab.L;
479 outRamp[l] = destLab.L;
480 }
481
482 // Make monotonic
483 for (l = 254; l > 0; --l) {
484 outRamp[l] = cmsmin(outRamp[l], outRamp[l+1]);
485 }
486
487 // Check
488 if (! (outRamp[0] < outRamp[255])) {
489
490 cmsDeleteTransform(hRoundTrip);
491 BlackPoint -> X = BlackPoint ->Y = BlackPoint -> Z = 0.0;
492 return FALSE;
493 }
494
495
496 // Test for mid range straight (only on relative colorimetric)
497 NearlyStraightMidrange = TRUE;
498 MinL = outRamp[0]; MaxL = outRamp[255];
499 if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
500
501 for (l=0; l < 256; l++) {
502
503 if (! ((inRamp[l] <= MinL + 0.2 * (MaxL - MinL) ) ||
504 (fabs(inRamp[l] - outRamp[l]) < 4.0 )))
505 NearlyStraightMidrange = FALSE;
506 }
507
508 // If the mid range is straight (as determined above) then the
509 // DestinationBlackPoint shall be the same as initialLab.
510 // Otherwise, the DestinationBlackPoint shall be determined
511 // using curve fitting.
512 if (NearlyStraightMidrange) {
513
514 cmsLab2XYZ(NULL, BlackPoint, &InitialLab);
515 cmsDeleteTransform(hRoundTrip);
516 return TRUE;
517 }
518 }
519
520
521 // curve fitting: The round-trip curve normally looks like a nearly constant section at the black point,
522 // with a corner and a nearly straight line to the white point.
523 for (l=0; l < 256; l++) {
524
525 yRamp[l] = (outRamp[l] - MinL) / (MaxL - MinL);
526 }
527
528 // find the black point using the least squares error quadratic curve fitting
529 if (Intent == INTENT_RELATIVE_COLORIMETRIC) {
530 lo = 0.1;
531 hi = 0.5;
532 }
533 else {
534
535 // Perceptual and saturation
536 lo = 0.03;
537 hi = 0.25;
538 }
539
540 // Capture shadow points for the fitting.
541 n = 0;
542 for (l=0; l < 256; l++) {
543
544 cmsFloat64Number ff = yRamp[l];
545
546 if (ff >= lo && ff < hi) {
547 x[n] = inRamp[l];
548 y[n] = yRamp[l];
|