OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorSpace.h" | 8 #include "SkColorSpace.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkEndian.h" | 10 #include "SkEndian.h" |
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
476 | 476 |
477 // Otherwise, fill in the interpolation table. | 477 // Otherwise, fill in the interpolation table. |
478 gammas[i].fTableSize = count; | 478 gammas[i].fTableSize = count; |
479 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); | 479 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); |
480 for (uint32_t j = 0; j < count; j++) { | 480 for (uint32_t j = 0; j < count; j++) { |
481 gammas[i].fTable[j] = | 481 gammas[i].fTable[j] = |
482 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f; | 482 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f; |
483 } | 483 } |
484 break; | 484 break; |
485 } | 485 } |
486 case kTAG_ParaCurveType: | 486 case kTAG_ParaCurveType: { |
487 // Determine the format of the parametric curve tag. | 487 // Determine the format of the parametric curve tag. |
488 switch(read_big_endian_short(src + 8)) { | 488 uint16_t format = read_big_endian_short(src + 8); |
scroggo
2016/06/01 21:23:12
Do these formats have names you can use?
msarett
2016/06/01 21:26:13
They don't, but that'd be nice. I may name them i
| |
489 case 0: { | 489 if (0 == format) { |
490 tagBytes = 12 + 4; | 490 tagBytes = 12 + 4; |
491 if (len < tagBytes) { | 491 if (len < tagBytes) { |
492 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); | 492 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); |
493 return false; | 493 return false; |
494 } | |
495 | |
496 // Y = X^g | |
497 int32_t g = read_big_endian_int(src + 12); | |
498 gammas[i].fValue = SkFixedToFloat(g); | |
499 break; | |
500 } | 494 } |
501 | 495 |
496 // Y = X^g | |
497 int32_t g = read_big_endian_int(src + 12); | |
498 gammas[i].fValue = SkFixedToFloat(g); | |
499 } else { | |
502 // Here's where the real parametric gammas start. There are many | 500 // Here's where the real parametric gammas start. There are many |
503 // permutations of the same equations. | 501 // permutations of the same equations. |
504 // | 502 // |
505 // Y = (aX + b)^g + c for X >= d | 503 // Y = (aX + b)^g + c for X >= d |
506 // Y = eX + f otherwise | 504 // Y = eX + f otherwise |
507 // | 505 // |
508 // We will fill in with zeros as necessary to always match t he above form. | 506 // We will fill in with zeros as necessary to always match t he above form. |
509 // Note that there is no need to actually write zero, since the struct is | 507 float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 0.0f, f = 0.0f; |
510 // zero initialized. | 508 switch(format) { |
511 case 1: { | 509 case 1: { |
512 tagBytes = 12 + 12; | 510 tagBytes = 12 + 12; |
513 if (len < tagBytes) { | 511 if (len < tagBytes) { |
514 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); | 512 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len); |
513 return false; | |
514 } | |
515 | |
516 // Y = (aX + b)^g for X >= -b/a | |
517 // Y = 0 otherwise | |
518 g = SkFixedToFloat(read_big_endian_int(src + 12)); | |
519 a = SkFixedToFloat(read_big_endian_int(src + 16)); | |
520 b = SkFixedToFloat(read_big_endian_int(src + 20)); | |
521 d = -b / a; | |
522 break; | |
523 } | |
524 case 2: | |
525 tagBytes = 12 + 16; | |
526 if (len < tagBytes) { | |
527 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len); | |
528 return false; | |
529 } | |
530 | |
531 // Y = (aX + b)^g + c for X >= -b/a | |
532 // Y = c otherwise | |
533 g = SkFixedToFloat(read_big_endian_int(src + 12)); | |
534 a = SkFixedToFloat(read_big_endian_int(src + 16)); | |
535 b = SkFixedToFloat(read_big_endian_int(src + 20)); | |
536 c = SkFixedToFloat(read_big_endian_int(src + 24)); | |
537 d = -b / a; | |
538 f = c; | |
539 break; | |
540 case 3: | |
541 tagBytes = 12 + 20; | |
542 if (len < tagBytes) { | |
543 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len); | |
544 return false; | |
545 } | |
546 | |
547 // Y = (aX + b)^g for X >= d | |
548 // Y = cX otherwise | |
549 g = SkFixedToFloat(read_big_endian_int(src + 12)); | |
550 a = SkFixedToFloat(read_big_endian_int(src + 16)); | |
551 b = SkFixedToFloat(read_big_endian_int(src + 20)); | |
552 d = SkFixedToFloat(read_big_endian_int(src + 28)); | |
553 e = SkFixedToFloat(read_big_endian_int(src + 24)); | |
554 break; | |
555 case 4: | |
556 tagBytes = 12 + 28; | |
557 if (len < tagBytes) { | |
558 SkColorSpacePrintf("gamma tag is too small (%d b ytes)", len); | |
559 return false; | |
560 } | |
561 | |
562 // Y = (aX + b)^g + c for X >= d | |
563 // Y = eX + f otherwise | |
564 // NOTE: The ICC spec writes "cX" in place of "eX" b ut I think | |
565 // it's a typo. | |
566 g = SkFixedToFloat(read_big_endian_int(src + 12)); | |
567 a = SkFixedToFloat(read_big_endian_int(src + 16)); | |
568 b = SkFixedToFloat(read_big_endian_int(src + 20)); | |
569 c = SkFixedToFloat(read_big_endian_int(src + 24)); | |
570 d = SkFixedToFloat(read_big_endian_int(src + 28)); | |
571 e = SkFixedToFloat(read_big_endian_int(src + 32)); | |
572 f = SkFixedToFloat(read_big_endian_int(src + 36)); | |
573 break; | |
574 default: | |
575 SkColorSpacePrintf("Invalid parametric curve type\n" ); | |
515 return false; | 576 return false; |
516 } | 577 } |
517 | 578 |
518 // Y = (aX + b)^g for X >= -b/a | 579 // Recognize and simplify a very common parametric represent ation of sRGB gamma. |
519 // Y = 0 otherwise | 580 if (color_space_almost_equal(0.9479f, a) && |
msarett
2016/06/01 21:01:19
Of my set of 10k jpegs with ICC profiles, 500 of t
| |
520 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); | 581 color_space_almost_equal(0.0521f, b) && |
521 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); | 582 color_space_almost_equal(0.0000f, c) && |
522 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); | 583 color_space_almost_equal(0.0405f, d) && |
523 gammas[i].fD = -gammas[i].fB / gammas[i].fA; | 584 color_space_almost_equal(0.0774f, e) && |
524 break; | 585 color_space_almost_equal(0.0000f, f) && |
586 color_space_almost_equal(2.4000f, g)) { | |
587 gammas[i].fValue = 2.2f; | |
588 } else { | |
589 gammas[i].fG = g; | |
590 gammas[i].fA = a; | |
591 gammas[i].fB = b; | |
592 gammas[i].fC = c; | |
593 gammas[i].fD = d; | |
594 gammas[i].fE = e; | |
595 gammas[i].fF = f; | |
525 } | 596 } |
526 case 2: | 597 } |
527 tagBytes = 12 + 16; | |
528 if (len < tagBytes) { | |
529 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); | |
530 return false; | |
531 } | |
532 | 598 |
533 // Y = (aX + b)^g + c for X >= -b/a | |
534 // Y = c otherwise | |
535 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); | |
536 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); | |
537 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); | |
538 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24)); | |
539 gammas[i].fD = -gammas[i].fB / gammas[i].fA; | |
540 gammas[i].fF = gammas[i].fC; | |
541 break; | |
542 case 3: | |
543 tagBytes = 12 + 20; | |
544 if (len < tagBytes) { | |
545 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); | |
546 return false; | |
547 } | |
548 | |
549 // Y = (aX + b)^g for X >= d | |
550 // Y = cX otherwise | |
551 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); | |
552 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); | |
553 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); | |
554 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28)); | |
555 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 24)); | |
556 break; | |
557 case 4: | |
558 tagBytes = 12 + 28; | |
559 if (len < tagBytes) { | |
560 SkColorSpacePrintf("gamma tag is too small (%d bytes )", len); | |
561 return false; | |
562 } | |
563 | |
564 // Y = (aX + b)^g + c for X >= d | |
565 // Y = eX + f otherwise | |
566 // NOTE: The ICC spec writes "cX" instead of "eX" but I think it's a typo. | |
567 gammas[i].fG = SkFixedToFloat(read_big_endian_int(src + 12)); | |
568 gammas[i].fA = SkFixedToFloat(read_big_endian_int(src + 16)); | |
569 gammas[i].fB = SkFixedToFloat(read_big_endian_int(src + 20)); | |
570 gammas[i].fC = SkFixedToFloat(read_big_endian_int(src + 24)); | |
571 gammas[i].fD = SkFixedToFloat(read_big_endian_int(src + 28)); | |
572 gammas[i].fE = SkFixedToFloat(read_big_endian_int(src + 32)); | |
573 gammas[i].fF = SkFixedToFloat(read_big_endian_int(src + 36)); | |
574 break; | |
575 default: | |
576 SkColorSpacePrintf("Invalid parametric curve type\n"); | |
577 return false; | |
578 } | |
579 break; | 599 break; |
600 } | |
580 default: | 601 default: |
581 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); | 602 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); |
582 return false; | 603 return false; |
583 } | 604 } |
584 | 605 |
585 // Adjust src and len if there is another gamma curve to load. | 606 // Adjust src and len if there is another gamma curve to load. |
586 if (i != numGammas - 1) { | 607 if (i != numGammas - 1) { |
587 // Each curve is padded to 4-byte alignment. | 608 // Each curve is padded to 4-byte alignment. |
588 tagBytes = SkAlign4(tagBytes); | 609 tagBytes = SkAlign4(tagBytes); |
589 if (len < tagBytes) { | 610 if (len < tagBytes) { |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1071 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1092 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
1072 ptr += kTAG_XYZ_Bytes; | 1093 ptr += kTAG_XYZ_Bytes; |
1073 | 1094 |
1074 // Write copyright tag | 1095 // Write copyright tag |
1075 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1096 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
1076 | 1097 |
1077 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if | 1098 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if |
1078 // the client calls again? | 1099 // the client calls again? |
1079 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1100 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
1080 } | 1101 } |
OLD | NEW |