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 |