Chromium Code Reviews| 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 |