| 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 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 } else if (len < tagBytes) { | 420 } else if (len < tagBytes) { |
| 421 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; | 421 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len)
; |
| 422 return false; | 422 return false; |
| 423 } | 423 } |
| 424 | 424 |
| 425 const uint16_t* table = (const uint16_t*) (src + 12); | 425 const uint16_t* table = (const uint16_t*) (src + 12); |
| 426 if (1 == count) { | 426 if (1 == count) { |
| 427 // The table entry is the gamma (with a bias of 256). | 427 // The table entry is the gamma (with a bias of 256). |
| 428 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); | 428 uint16_t value = read_big_endian_short((const uint8_t*) tabl
e); |
| 429 gammas[i].fValue = value / 256.0f; | 429 gammas[i].fValue = value / 256.0f; |
| 430 if (0.0f == gammas[i].fValue) { |
| 431 SkColorSpacePrintf("Cannot have zero gamma value"); |
| 432 return false; |
| 433 } |
| 430 SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue)
; | 434 SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue)
; |
| 431 break; | 435 break; |
| 432 } | 436 } |
| 433 | 437 |
| 434 // Check for frequently occurring curves and use a fast approxim
ation. | 438 // Check for frequently occurring curves and use a fast approxim
ation. |
| 435 // We do this by sampling a few values and see if they match our
expectation. | 439 // We do this by sampling a few values and see if they match our
expectation. |
| 436 // A more robust solution would be to compare each value in this
curve against | 440 // A more robust solution would be to compare each value in this
curve against |
| 437 // a 2.2f curve see if we remain below an error threshold. At t
his time, | 441 // a 2.2f curve see if we remain below an error threshold. At t
his time, |
| 438 // we haven't seen any images in the wild that make this kind of | 442 // we haven't seen any images in the wild that make this kind of |
| 439 // calculation necessary. We encounter identical gamma curves o
ver and | 443 // calculation necessary. We encounter identical gamma curves o
ver and |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 510 tagBytes = 12 + 12; | 514 tagBytes = 12 + 12; |
| 511 if (len < tagBytes) { | 515 if (len < tagBytes) { |
| 512 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); | 516 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); |
| 513 return false; | 517 return false; |
| 514 } | 518 } |
| 515 | 519 |
| 516 // Y = (aX + b)^g for X >= -b/a | 520 // Y = (aX + b)^g for X >= -b/a |
| 517 // Y = 0 otherwise | 521 // Y = 0 otherwise |
| 518 g = SkFixedToFloat(read_big_endian_int(src + 12)); | 522 g = SkFixedToFloat(read_big_endian_int(src + 12)); |
| 519 a = SkFixedToFloat(read_big_endian_int(src + 16)); | 523 a = SkFixedToFloat(read_big_endian_int(src + 16)); |
| 524 if (0.0f == a) { |
| 525 return false; |
| 526 } |
| 527 |
| 520 b = SkFixedToFloat(read_big_endian_int(src + 20)); | 528 b = SkFixedToFloat(read_big_endian_int(src + 20)); |
| 521 d = -b / a; | 529 d = -b / a; |
| 522 break; | 530 break; |
| 523 } | 531 } |
| 524 case 2: | 532 case 2: |
| 525 tagBytes = 12 + 16; | 533 tagBytes = 12 + 16; |
| 526 if (len < tagBytes) { | 534 if (len < tagBytes) { |
| 527 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); | 535 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); |
| 528 return false; | 536 return false; |
| 529 } | 537 } |
| 530 | 538 |
| 531 // Y = (aX + b)^g + c for X >= -b/a | 539 // Y = (aX + b)^g + c for X >= -b/a |
| 532 // Y = c otherwise | 540 // Y = c otherwise |
| 533 g = SkFixedToFloat(read_big_endian_int(src + 12)); | 541 g = SkFixedToFloat(read_big_endian_int(src + 12)); |
| 534 a = SkFixedToFloat(read_big_endian_int(src + 16)); | 542 a = SkFixedToFloat(read_big_endian_int(src + 16)); |
| 543 if (0.0f == a) { |
| 544 return false; |
| 545 } |
| 546 |
| 535 b = SkFixedToFloat(read_big_endian_int(src + 20)); | 547 b = SkFixedToFloat(read_big_endian_int(src + 20)); |
| 536 c = SkFixedToFloat(read_big_endian_int(src + 24)); | 548 c = SkFixedToFloat(read_big_endian_int(src + 24)); |
| 537 d = -b / a; | 549 d = -b / a; |
| 538 f = c; | 550 f = c; |
| 539 break; | 551 break; |
| 540 case 3: | 552 case 3: |
| 541 tagBytes = 12 + 20; | 553 tagBytes = 12 + 20; |
| 542 if (len < tagBytes) { | 554 if (len < tagBytes) { |
| 543 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); | 555 SkColorSpacePrintf("gamma tag is too small (%d b
ytes)", len); |
| 544 return false; | 556 return false; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 // Recognize and simplify a very common parametric represent
ation of sRGB gamma. | 591 // Recognize and simplify a very common parametric represent
ation of sRGB gamma. |
| 580 if (color_space_almost_equal(0.9479f, a) && | 592 if (color_space_almost_equal(0.9479f, a) && |
| 581 color_space_almost_equal(0.0521f, b) && | 593 color_space_almost_equal(0.0521f, b) && |
| 582 color_space_almost_equal(0.0000f, c) && | 594 color_space_almost_equal(0.0000f, c) && |
| 583 color_space_almost_equal(0.0405f, d) && | 595 color_space_almost_equal(0.0405f, d) && |
| 584 color_space_almost_equal(0.0774f, e) && | 596 color_space_almost_equal(0.0774f, e) && |
| 585 color_space_almost_equal(0.0000f, f) && | 597 color_space_almost_equal(0.0000f, f) && |
| 586 color_space_almost_equal(2.4000f, g)) { | 598 color_space_almost_equal(2.4000f, g)) { |
| 587 gammas[i].fValue = 2.2f; | 599 gammas[i].fValue = 2.2f; |
| 588 } else { | 600 } else { |
| 601 // Fail on invalid gammas. |
| 602 if (d <= 0.0f) { |
| 603 // Y = (aX + b)^g + c for always |
| 604 if (0.0f == a || 0.0f == g) { |
| 605 SkColorSpacePrintf("A or G is zero, constant gam
ma function " |
| 606 "is nonsense"); |
| 607 return false; |
| 608 } |
| 609 } else if (d >= 1.0f) { |
| 610 // Y = eX + f for always |
| 611 if (0.0f == e) { |
| 612 SkColorSpacePrintf("E is zero, constant gamma fu
nction is " |
| 613 "nonsense"); |
| 614 return false; |
| 615 } |
| 616 } else if ((0.0f == a || 0.0f == g) && 0.0f == e) { |
| 617 SkColorSpacePrintf("A or G, and E are zero, constant
gamma function " |
| 618 "is nonsense"); |
| 619 return false; |
| 620 } |
| 621 |
| 589 gammas[i].fG = g; | 622 gammas[i].fG = g; |
| 590 gammas[i].fA = a; | 623 gammas[i].fA = a; |
| 591 gammas[i].fB = b; | 624 gammas[i].fB = b; |
| 592 gammas[i].fC = c; | 625 gammas[i].fC = c; |
| 593 gammas[i].fD = d; | 626 gammas[i].fD = d; |
| 594 gammas[i].fE = e; | 627 gammas[i].fE = e; |
| 595 gammas[i].fF = f; | 628 gammas[i].fF = f; |
| 596 } | 629 } |
| 597 } | 630 } |
| 598 | 631 |
| 599 break; | 632 break; |
| 600 } | 633 } |
| 601 default: | 634 default: |
| 602 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); | 635 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); |
| 603 return false; | 636 return false; |
| 604 } | 637 } |
| 605 | 638 |
| 639 // Ensure that we have successfully read a gamma representation. |
| 640 SkASSERT(gammas[i].isValue() || gammas[i].isTable() || gammas[i].isParam
etric()); |
| 641 |
| 606 // Adjust src and len if there is another gamma curve to load. | 642 // Adjust src and len if there is another gamma curve to load. |
| 607 if (i != numGammas - 1) { | 643 if (i != numGammas - 1) { |
| 608 // Each curve is padded to 4-byte alignment. | 644 // Each curve is padded to 4-byte alignment. |
| 609 tagBytes = SkAlign4(tagBytes); | 645 tagBytes = SkAlign4(tagBytes); |
| 610 if (len < tagBytes) { | 646 if (len < tagBytes) { |
| 611 return false; | 647 return false; |
| 612 } | 648 } |
| 613 | 649 |
| 614 src += tagBytes; | 650 src += tagBytes; |
| 615 len -= tagBytes; | 651 len -= tagBytes; |
| (...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 ptr32[4] = SkEndian_SwapBE32(0x000116cc); | 1128 ptr32[4] = SkEndian_SwapBE32(0x000116cc); |
| 1093 ptr += kTAG_XYZ_Bytes; | 1129 ptr += kTAG_XYZ_Bytes; |
| 1094 | 1130 |
| 1095 // Write copyright tag | 1131 // Write copyright tag |
| 1096 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); | 1132 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); |
| 1097 | 1133 |
| 1098 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if | 1134 // TODO (msarett): Should we try to hold onto the data so we can return imme
diately if |
| 1099 // the client calls again? | 1135 // the client calls again? |
| 1100 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); | 1136 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); |
| 1101 } | 1137 } |
| OLD | NEW |