| 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 "SkAtomics.h" | 8 #include "SkAtomics.h" |
| 9 #include "SkColorSpace.h" | 9 #include "SkColorSpace.h" |
| 10 | 10 |
| 11 void SkFloat3::dump() const { | 11 void SkFloat3::dump() const { |
| 12 SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]); | 12 SkDebugf("[%7.4f %7.4f %7.4f]\n", fVec[0], fVec[1], fVec[2]); |
| 13 } | 13 } |
| 14 | 14 |
| 15 void SkFloat3x3::dump() const { | |
| 16 SkDebugf("[%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f] [%7.4f %7.4f %7.4f]\n", | |
| 17 fMat[0], fMat[1], fMat[2], | |
| 18 fMat[3], fMat[4], fMat[5], | |
| 19 fMat[6], fMat[7], fMat[8]); | |
| 20 } | |
| 21 | |
| 22 ////////////////////////////////////////////////////////////////////////////////
////////////////// | 15 ////////////////////////////////////////////////////////////////////////////////
////////////////// |
| 23 | 16 |
| 24 static int32_t gUniqueColorSpaceID; | 17 static int32_t gUniqueColorSpaceID; |
| 25 | 18 |
| 26 SkColorSpace::SkColorSpace(SkGammas gammas, const SkFloat3x3& toXYZD50, Named na
med) | 19 SkColorSpace::SkColorSpace(SkGammas gammas, const SkMatrix44& toXYZD50, Named na
med) |
| 27 : fGammas(std::move(gammas)) | 20 : fGammas(std::move(gammas)) |
| 28 , fToXYZD50(toXYZD50) | 21 , fToXYZD50(toXYZD50) |
| 29 , fToXYZOffset({{ 0.0f, 0.0f, 0.0f }}) | |
| 30 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) | 22 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) |
| 31 , fNamed(named) | 23 , fNamed(named) |
| 32 {} | 24 {} |
| 33 | 25 |
| 34 SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, SkGammas gammas, | 26 SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, SkGammas gammas, |
| 35 const SkFloat3x3& toXYZD50, const SkFloat3& toXYZOffs
et) | 27 const SkMatrix44& toXYZD50) |
| 36 : fColorLUT(std::move(colorLUT)) | 28 : fColorLUT(std::move(colorLUT)) |
| 37 , fGammas(std::move(gammas)) | 29 , fGammas(std::move(gammas)) |
| 38 , fToXYZD50(toXYZD50) | 30 , fToXYZD50(toXYZD50) |
| 39 , fToXYZOffset(toXYZOffset) | |
| 40 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) | 31 , fUniqueID(sk_atomic_inc(&gUniqueColorSpaceID)) |
| 41 , fNamed(kUnknown_Named) | 32 , fNamed(kUnknown_Named) |
| 42 {} | 33 {} |
| 43 | 34 |
| 44 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkFloat3x3& toXYZD50, SkGammas ga
mmas) { | 35 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkMatrix44& toXYZD50, SkGammas ga
mmas) { |
| 45 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUn
known_Named)); | 36 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(gammas), toXYZD50, kUn
known_Named)); |
| 46 } | 37 } |
| 47 | 38 |
| 48 const SkFloat3x3 gSRGB_toXYZD50 {{ | 39 const float gSRGB_toXYZD50[] { |
| 49 0.4358f, 0.2224f, 0.0139f, // * R | 40 0.4358f, 0.2224f, 0.0139f, // * R |
| 50 0.3853f, 0.7170f, 0.0971f, // * G | 41 0.3853f, 0.7170f, 0.0971f, // * G |
| 51 0.1430f, 0.0606f, 0.7139f, // * B | 42 0.1430f, 0.0606f, 0.7139f, // * B |
| 52 }}; | 43 }; |
| 53 | 44 |
| 54 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 45 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { |
| 55 switch (named) { | 46 switch (named) { |
| 56 case kSRGB_Named: | 47 case kSRGB_Named: { |
| 57 return sk_sp<SkColorSpace>(new SkColorSpace(SkGammas(2.2f, 2.2f, 2.2
f), gSRGB_toXYZD50, | 48 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
| 49 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50); |
| 50 return sk_sp<SkColorSpace>(new SkColorSpace(SkGammas(2.2f, 2.2f, 2.2
f), srgbToxyzD50, |
| 58 kSRGB_Named)); | 51 kSRGB_Named)); |
| 52 } |
| 59 default: | 53 default: |
| 60 break; | 54 break; |
| 61 } | 55 } |
| 62 return nullptr; | 56 return nullptr; |
| 63 } | 57 } |
| 64 | 58 |
| 65 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 59 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
| 66 | 60 |
| 67 #include "SkFixed.h" | 61 #include "SkFixed.h" |
| 68 #include "SkTemplates.h" | 62 #include "SkTemplates.h" |
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 if (1 == precision) { | 401 if (1 == precision) { |
| 408 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; | 402 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |
| 409 } else { | 403 } else { |
| 410 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; | 404 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; |
| 411 } | 405 } |
| 412 } | 406 } |
| 413 | 407 |
| 414 return true; | 408 return true; |
| 415 } | 409 } |
| 416 | 410 |
| 417 bool load_matrix(SkFloat3x3* toXYZ, SkFloat3* toXYZOffset, const uint8_t* src, s
ize_t len) { | 411 bool load_matrix(SkMatrix44* toXYZ, const uint8_t* src, size_t len) { |
| 418 if (len < 48) { | 412 if (len < 48) { |
| 419 SkColorSpacePrintf("Matrix tag is too small (%d bytes).", len); | 413 SkColorSpacePrintf("Matrix tag is too small (%d bytes).", len); |
| 420 return false; | 414 return false; |
| 421 } | 415 } |
| 422 | 416 |
| 423 toXYZ->fMat[0] = SkFixedToFloat(read_big_endian_int(src)); | 417 float array[16]; |
| 424 toXYZ->fMat[3] = SkFixedToFloat(read_big_endian_int(src + 4)); | 418 array[ 0] = SkFixedToFloat(read_big_endian_int(src)); |
| 425 toXYZ->fMat[6] = SkFixedToFloat(read_big_endian_int(src + 8)); | 419 array[ 1] = SkFixedToFloat(read_big_endian_int(src + 4)); |
| 426 toXYZ->fMat[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 420 array[ 2] = SkFixedToFloat(read_big_endian_int(src + 8)); |
| 427 toXYZ->fMat[4] = SkFixedToFloat(read_big_endian_int(src + 16)); | 421 array[ 3] = 0; |
| 428 toXYZ->fMat[7] = SkFixedToFloat(read_big_endian_int(src + 20)); | 422 array[ 4] = SkFixedToFloat(read_big_endian_int(src + 12)); |
| 429 toXYZ->fMat[2] = SkFixedToFloat(read_big_endian_int(src + 24)); | 423 array[ 5] = SkFixedToFloat(read_big_endian_int(src + 16)); |
| 430 toXYZ->fMat[5] = SkFixedToFloat(read_big_endian_int(src + 28)); | 424 array[ 6] = SkFixedToFloat(read_big_endian_int(src + 20)); |
| 431 toXYZ->fMat[8] = SkFixedToFloat(read_big_endian_int(src + 32)); | 425 array[ 7] = 0; |
| 432 toXYZOffset->fVec[0] = SkFixedToFloat(read_big_endian_int(src + 36)); | 426 array[ 8] = SkFixedToFloat(read_big_endian_int(src + 24)); |
| 433 toXYZOffset->fVec[1] = SkFixedToFloat(read_big_endian_int(src + 40)); | 427 array[ 9] = SkFixedToFloat(read_big_endian_int(src + 28)); |
| 434 toXYZOffset->fVec[2] = SkFixedToFloat(read_big_endian_int(src + 44)); | 428 array[10] = SkFixedToFloat(read_big_endian_int(src + 32)); |
| 429 array[11] = 0; |
| 430 array[12] = SkFixedToFloat(read_big_endian_int(src + 36)); // translate R |
| 431 array[13] = SkFixedToFloat(read_big_endian_int(src + 40)); // translate G |
| 432 array[14] = SkFixedToFloat(read_big_endian_int(src + 44)); |
| 433 array[15] = 1; |
| 434 toXYZ->setColMajorf(array); |
| 435 return true; | 435 return true; |
| 436 } | 436 } |
| 437 | 437 |
| 438 bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammas* gammas, SkFl
oat3x3* toXYZ, | 438 bool SkColorSpace::LoadA2B0(SkColorLookUpTable* colorLUT, SkGammas* gammas, SkMa
trix44* toXYZ, |
| 439 SkFloat3* toXYZOffset, const uint8_t* src, size_t le
n) { | 439 const uint8_t* src, size_t len) { |
| 440 if (len < 32) { | 440 if (len < 32) { |
| 441 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); | 441 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); |
| 442 return false; | 442 return false; |
| 443 } | 443 } |
| 444 | 444 |
| 445 uint32_t type = read_big_endian_uint(src); | 445 uint32_t type = read_big_endian_uint(src); |
| 446 if (kTAG_AtoBType != type) { | 446 if (kTAG_AtoBType != type) { |
| 447 // FIXME (msarett): Need to support lut8Type and lut16Type. | 447 // FIXME (msarett): Need to support lut8Type and lut16Type. |
| 448 SkColorSpacePrintf("Unsupported A to B tag type.\n"); | 448 SkColorSpacePrintf("Unsupported A to B tag type.\n"); |
| 449 return false; | 449 return false; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 uint32_t offsetToMCurves = read_big_endian_int(src + 20); | 486 uint32_t offsetToMCurves = read_big_endian_int(src + 20); |
| 487 if (0 != offsetToMCurves && offsetToMCurves < len) { | 487 if (0 != offsetToMCurves && offsetToMCurves < len) { |
| 488 if (!SkColorSpace::LoadGammas(&gammas->fRed, outputChannels, src + offse
tToMCurves, | 488 if (!SkColorSpace::LoadGammas(&gammas->fRed, outputChannels, src + offse
tToMCurves, |
| 489 len - offsetToMCurves)) { | 489 len - offsetToMCurves)) { |
| 490 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); | 490 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); |
| 491 } | 491 } |
| 492 } | 492 } |
| 493 | 493 |
| 494 uint32_t offsetToMatrix = read_big_endian_int(src + 16); | 494 uint32_t offsetToMatrix = read_big_endian_int(src + 16); |
| 495 if (0 != offsetToMatrix && offsetToMatrix < len) { | 495 if (0 != offsetToMatrix && offsetToMatrix < len) { |
| 496 if (!load_matrix(toXYZ, toXYZOffset, src + offsetToMatrix, len - offsetT
oMatrix)) { | 496 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { |
| 497 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 497 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
| 498 } | 498 } |
| 499 } | 499 } |
| 500 | 500 |
| 501 return true; | 501 return true; |
| 502 } | 502 } |
| 503 | 503 |
| 504 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) { | 504 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) { |
| 505 const uint8_t* ptr = (const uint8_t*) base; | 505 const uint8_t* ptr = (const uint8_t*) base; |
| 506 | 506 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 } | 544 } |
| 545 } | 545 } |
| 546 | 546 |
| 547 switch (header.fInputColorSpace) { | 547 switch (header.fInputColorSpace) { |
| 548 case kRGB_ColorSpace: { | 548 case kRGB_ColorSpace: { |
| 549 // Recognize the rXYZ, gXYZ, and bXYZ tags. | 549 // Recognize the rXYZ, gXYZ, and bXYZ tags. |
| 550 const ICCTag* r = ICCTag::Find(tags.get(), tagCount, kTAG_rXYZ); | 550 const ICCTag* r = ICCTag::Find(tags.get(), tagCount, kTAG_rXYZ); |
| 551 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); | 551 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); |
| 552 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); | 552 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); |
| 553 if (r && g && b) { | 553 if (r && g && b) { |
| 554 SkFloat3x3 toXYZ; | 554 float toXYZ[9]; |
| 555 if (!load_xyz(&toXYZ.fMat[0], r->addr((const uint8_t*) base), r-
>fLength) || | 555 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen
gth) || |
| 556 !load_xyz(&toXYZ.fMat[3], g->addr((const uint8_t*) base), g-
>fLength) || | 556 !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen
gth) || |
| 557 !load_xyz(&toXYZ.fMat[6], b->addr((const uint8_t*) base), b-
>fLength)) | 557 !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen
gth)) |
| 558 { | 558 { |
| 559 return_null("Need valid rgb tags for XYZ space"); | 559 return_null("Need valid rgb tags for XYZ space"); |
| 560 } | 560 } |
| 561 | 561 |
| 562 // It is not uncommon to see missing or empty gamma tags. This
indicates | 562 // It is not uncommon to see missing or empty gamma tags. This
indicates |
| 563 // that we should use unit gamma. | 563 // that we should use unit gamma. |
| 564 SkGammas gammas; | 564 SkGammas gammas; |
| 565 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); | 565 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); |
| 566 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); | 566 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); |
| 567 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); | 567 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); |
| 568 if (!r || !SkColorSpace::LoadGammas(&gammas.fRed, 1, | 568 if (!r || !SkColorSpace::LoadGammas(&gammas.fRed, 1, |
| 569 r->addr((const uint8_t*) bas
e), r->fLength)) { | 569 r->addr((const uint8_t*) bas
e), r->fLength)) { |
| 570 SkColorSpacePrintf("Failed to read R gamma tag.\n"); | 570 SkColorSpacePrintf("Failed to read R gamma tag.\n"); |
| 571 } | 571 } |
| 572 if (!g || !SkColorSpace::LoadGammas(&gammas.fGreen, 1, | 572 if (!g || !SkColorSpace::LoadGammas(&gammas.fGreen, 1, |
| 573 g->addr((const uint8_t*) bas
e), g->fLength)) { | 573 g->addr((const uint8_t*) bas
e), g->fLength)) { |
| 574 SkColorSpacePrintf("Failed to read G gamma tag.\n"); | 574 SkColorSpacePrintf("Failed to read G gamma tag.\n"); |
| 575 } | 575 } |
| 576 if (!b || !SkColorSpace::LoadGammas(&gammas.fBlue, 1, | 576 if (!b || !SkColorSpace::LoadGammas(&gammas.fBlue, 1, |
| 577 b->addr((const uint8_t*) bas
e), b->fLength)) { | 577 b->addr((const uint8_t*) bas
e), b->fLength)) { |
| 578 SkColorSpacePrintf("Failed to read B gamma tag.\n"); | 578 SkColorSpacePrintf("Failed to read B gamma tag.\n"); |
| 579 } | 579 } |
| 580 return SkColorSpace::NewRGB(toXYZ, std::move(gammas)); | 580 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| 581 mat.set3x3ColMajorf(toXYZ); |
| 582 return SkColorSpace::NewRGB(mat, std::move(gammas)); |
| 581 } | 583 } |
| 582 | 584 |
| 583 // Recognize color profile specified by A2B0 tag. | 585 // Recognize color profile specified by A2B0 tag. |
| 584 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); | 586 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); |
| 585 if (a2b0) { | 587 if (a2b0) { |
| 586 SkColorLookUpTable colorLUT; | 588 SkColorLookUpTable colorLUT; |
| 587 SkGammas gammas; | 589 SkGammas gammas; |
| 588 SkFloat3x3 toXYZ; | 590 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
| 589 SkFloat3 toXYZOffset; | 591 if (!SkColorSpace::LoadA2B0(&colorLUT, &gammas, &toXYZ, |
| 590 if (!SkColorSpace::LoadA2B0(&colorLUT, &gammas, &toXYZ, &toXYZOf
fset, | |
| 591 a2b0->addr((const uint8_t*) base), a
2b0->fLength)) { | 592 a2b0->addr((const uint8_t*) base), a
2b0->fLength)) { |
| 592 return_null("Failed to parse A2B0 tag"); | 593 return_null("Failed to parse A2B0 tag"); |
| 593 } | 594 } |
| 594 | 595 |
| 595 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
std::move(gammas), | 596 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
std::move(gammas), |
| 596 toXYZ, toXYZOffset))
; | 597 toXYZ)); |
| 597 } | 598 } |
| 598 | 599 |
| 599 } | 600 } |
| 600 default: | 601 default: |
| 601 break; | 602 break; |
| 602 } | 603 } |
| 603 | 604 |
| 604 return_null("ICC profile contains unsupported colorspace"); | 605 return_null("ICC profile contains unsupported colorspace"); |
| 605 } | 606 } |
| OLD | NEW |