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(const SkFloat3& gamma, const SkFloat3x3& toXYZD50, Na
med named) | 19 SkColorSpace::SkColorSpace(const SkFloat3& gamma, const SkMatrix44& toXYZD50, Na
med named) |
27 : fGamma(gamma) | 20 : fGamma(gamma) |
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, const SkFloat3& gamma, | 26 SkColorSpace::SkColorSpace(SkColorLookUpTable colorLUT, const SkFloat3& gamma, |
35 const SkFloat3x3& toXYZD50, const SkFloat3& toXYZOffs
et) | 27 const SkMatrix44& toXYZD50) |
36 : fColorLUT(std::move(colorLUT)) | 28 : fColorLUT(std::move(colorLUT)) |
37 , fGamma(gamma) | 29 , fGamma(gamma) |
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, const SkFlo
at3& gamma) { | 35 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const SkMatrix44& toXYZD50, const SkFlo
at3& gamma) { |
45 return sk_sp<SkColorSpace>(new SkColorSpace(gamma, toXYZD50, kUnknown_Named)
); | 36 return sk_sp<SkColorSpace>(new SkColorSpace(gamma, toXYZD50, kUnknown_Named)
); |
46 } | 37 } |
47 | 38 |
48 const SkFloat3 gSRGB_gamma {{ 2.2f, 2.2f, 2.2f }}; | 39 const SkFloat3 gSRGB_gamma {{ 2.2f, 2.2f, 2.2f }}; |
49 const SkFloat3x3 gSRGB_toXYZD50 {{ | 40 const float gSRGB_toXYZD50[9] { |
50 0.4358f, 0.2224f, 0.0139f, // * R | 41 0.4358f, 0.2224f, 0.0139f, // * R |
51 0.3853f, 0.7170f, 0.0971f, // * G | 42 0.3853f, 0.7170f, 0.0971f, // * G |
52 0.1430f, 0.0606f, 0.7139f, // * B | 43 0.1430f, 0.0606f, 0.7139f, // * B |
53 }}; | 44 }; |
54 | 45 |
55 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { | 46 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { |
56 switch (named) { | 47 switch (named) { |
57 case kSRGB_Named: | 48 case kSRGB_Named: { |
58 return sk_sp<SkColorSpace>(new SkColorSpace(gSRGB_gamma, gSRGB_toXYZ
D50, kSRGB_Named)); | 49 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); |
| 50 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50); |
| 51 return sk_sp<SkColorSpace>(new SkColorSpace(gSRGB_gamma, srgbToxyzD5
0, 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 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 if (1 == precision) { | 407 if (1 == precision) { |
414 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; | 408 colorLUT->fTable[i] = ((float) ptr[i]) / 255.0f; |
415 } else { | 409 } else { |
416 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; | 410 colorLUT->fTable[i] = ((float) read_big_endian_short(ptr)) / 65535.0
f; |
417 } | 411 } |
418 } | 412 } |
419 | 413 |
420 return true; | 414 return true; |
421 } | 415 } |
422 | 416 |
423 bool load_matrix(SkFloat3x3* toXYZ, SkFloat3* toXYZOffset, const uint8_t* src, s
ize_t len) { | 417 bool load_matrix(SkMatrix44* toXYZ, const uint8_t* src, size_t len) { |
424 if (len < 48) { | 418 if (len < 48) { |
425 SkColorSpacePrintf("Matrix tag is too small (%d bytes).", len); | 419 SkColorSpacePrintf("Matrix tag is too small (%d bytes).", len); |
426 return false; | 420 return false; |
427 } | 421 } |
428 | 422 |
429 toXYZ->fMat[0] = SkFixedToFloat(read_big_endian_int(src)); | 423 float array[16]; |
430 toXYZ->fMat[3] = SkFixedToFloat(read_big_endian_int(src + 4)); | 424 array[ 0] = SkFixedToFloat(read_big_endian_int(src)); |
431 toXYZ->fMat[6] = SkFixedToFloat(read_big_endian_int(src + 8)); | 425 array[ 1] = SkFixedToFloat(read_big_endian_int(src + 4)); |
432 toXYZ->fMat[1] = SkFixedToFloat(read_big_endian_int(src + 12)); | 426 array[ 2] = SkFixedToFloat(read_big_endian_int(src + 8)); |
433 toXYZ->fMat[4] = SkFixedToFloat(read_big_endian_int(src + 16)); | 427 array[ 3] = 0; |
434 toXYZ->fMat[7] = SkFixedToFloat(read_big_endian_int(src + 20)); | 428 array[ 4] = SkFixedToFloat(read_big_endian_int(src + 12)); |
435 toXYZ->fMat[2] = SkFixedToFloat(read_big_endian_int(src + 24)); | 429 array[ 5] = SkFixedToFloat(read_big_endian_int(src + 16)); |
436 toXYZ->fMat[5] = SkFixedToFloat(read_big_endian_int(src + 28)); | 430 array[ 6] = SkFixedToFloat(read_big_endian_int(src + 20)); |
437 toXYZ->fMat[8] = SkFixedToFloat(read_big_endian_int(src + 32)); | 431 array[ 7] = 0; |
438 toXYZOffset->fVec[0] = SkFixedToFloat(read_big_endian_int(src + 36)); | 432 array[ 8] = SkFixedToFloat(read_big_endian_int(src + 24)); |
439 toXYZOffset->fVec[1] = SkFixedToFloat(read_big_endian_int(src + 40)); | 433 array[ 9] = SkFixedToFloat(read_big_endian_int(src + 28)); |
440 toXYZOffset->fVec[2] = SkFixedToFloat(read_big_endian_int(src + 44)); | 434 array[10] = SkFixedToFloat(read_big_endian_int(src + 32)); |
| 435 array[11] = 0; |
| 436 array[12] = SkFixedToFloat(read_big_endian_int(src + 36)); // translate R |
| 437 array[13] = SkFixedToFloat(read_big_endian_int(src + 40)); // translate G |
| 438 array[14] = SkFixedToFloat(read_big_endian_int(src + 44)); |
| 439 array[15] = 1; |
| 440 toXYZ->setColMajorf(array); |
441 return true; | 441 return true; |
442 } | 442 } |
443 | 443 |
444 bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkFloat3x3* toXYZ, | 444 bool load_a2b0(SkColorLookUpTable* colorLUT, SkFloat3* gamma, SkMatrix44* toXYZ, |
445 SkFloat3* toXYZOffset, const uint8_t* src, size_t len) { | 445 const uint8_t* src, size_t len) { |
446 if (len < 32) { | 446 if (len < 32) { |
447 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); | 447 SkColorSpacePrintf("A to B tag is too small (%d bytes).", len); |
448 return false; | 448 return false; |
449 } | 449 } |
450 | 450 |
451 uint32_t type = read_big_endian_uint(src); | 451 uint32_t type = read_big_endian_uint(src); |
452 if (kTAG_AtoBType != type) { | 452 if (kTAG_AtoBType != type) { |
453 // FIXME (msarett): Need to support lut8Type and lut16Type. | 453 // FIXME (msarett): Need to support lut8Type and lut16Type. |
454 SkColorSpacePrintf("Unsupported A to B tag type.\n"); | 454 SkColorSpacePrintf("Unsupported A to B tag type.\n"); |
455 return false; | 455 return false; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
492 uint32_t offsetToMCurves = read_big_endian_int(src + 20); | 492 uint32_t offsetToMCurves = read_big_endian_int(src + 20); |
493 if (0 != offsetToMCurves && offsetToMCurves < len) { | 493 if (0 != offsetToMCurves && offsetToMCurves < len) { |
494 if (!load_gammas(gamma->fVec, outputChannels, src + offsetToMCurves, len
- offsetToMCurves)) | 494 if (!load_gammas(gamma->fVec, outputChannels, src + offsetToMCurves, len
- offsetToMCurves)) |
495 { | 495 { |
496 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); | 496 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); |
497 } | 497 } |
498 } | 498 } |
499 | 499 |
500 uint32_t offsetToMatrix = read_big_endian_int(src + 16); | 500 uint32_t offsetToMatrix = read_big_endian_int(src + 16); |
501 if (0 != offsetToMatrix && offsetToMatrix < len) { | 501 if (0 != offsetToMatrix && offsetToMatrix < len) { |
502 if (!load_matrix(toXYZ, toXYZOffset, src + offsetToMatrix, len - offsetT
oMatrix)) { | 502 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { |
503 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); | 503 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); |
504 } | 504 } |
505 } | 505 } |
506 | 506 |
507 return true; | 507 return true; |
508 } | 508 } |
509 | 509 |
510 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) { | 510 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* base, size_t len) { |
511 const uint8_t* ptr = (const uint8_t*) base; | 511 const uint8_t* ptr = (const uint8_t*) base; |
512 | 512 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 } | 550 } |
551 } | 551 } |
552 | 552 |
553 switch (header.fInputColorSpace) { | 553 switch (header.fInputColorSpace) { |
554 case kRGB_ColorSpace: { | 554 case kRGB_ColorSpace: { |
555 // Recognize the rXYZ, gXYZ, and bXYZ tags. | 555 // Recognize the rXYZ, gXYZ, and bXYZ tags. |
556 const ICCTag* r = ICCTag::Find(tags.get(), tagCount, kTAG_rXYZ); | 556 const ICCTag* r = ICCTag::Find(tags.get(), tagCount, kTAG_rXYZ); |
557 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); | 557 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); |
558 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); | 558 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); |
559 if (r && g && b) { | 559 if (r && g && b) { |
560 SkFloat3x3 toXYZ; | 560 float toXYZ[9]; |
561 if (!load_xyz(&toXYZ.fMat[0], r->addr((const uint8_t*) base), r-
>fLength) || | 561 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen
gth) || |
562 !load_xyz(&toXYZ.fMat[3], g->addr((const uint8_t*) base), g-
>fLength) || | 562 !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen
gth) || |
563 !load_xyz(&toXYZ.fMat[6], b->addr((const uint8_t*) base), b-
>fLength)) | 563 !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen
gth)) |
564 { | 564 { |
565 return_null("Need valid rgb tags for XYZ space"); | 565 return_null("Need valid rgb tags for XYZ space"); |
566 } | 566 } |
567 | 567 |
568 // It is not uncommon to see missing or empty gamma tags. This
indicates | 568 // It is not uncommon to see missing or empty gamma tags. This
indicates |
569 // that we should use unit gamma. | 569 // that we should use unit gamma. |
570 SkFloat3 gamma {{ 1.0f, 1.0f, 1.0f }}; | 570 SkFloat3 gamma {{ 1.0f, 1.0f, 1.0f }}; |
571 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); | 571 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); |
572 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); | 572 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); |
573 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); | 573 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); |
574 if (!r || | 574 if (!r || |
575 !load_gammas(&gamma.fVec[0], 1, r->addr((const uint8_t*) bas
e), r->fLength)) | 575 !load_gammas(&gamma.fVec[0], 1, r->addr((const uint8_t*) bas
e), r->fLength)) |
576 { | 576 { |
577 SkColorSpacePrintf("Failed to read R gamma tag.\n"); | 577 SkColorSpacePrintf("Failed to read R gamma tag.\n"); |
578 } | 578 } |
579 if (!g || | 579 if (!g || |
580 !load_gammas(&gamma.fVec[1], 1, g->addr((const uint8_t*) bas
e), g->fLength)) | 580 !load_gammas(&gamma.fVec[1], 1, g->addr((const uint8_t*) bas
e), g->fLength)) |
581 { | 581 { |
582 SkColorSpacePrintf("Failed to read G gamma tag.\n"); | 582 SkColorSpacePrintf("Failed to read G gamma tag.\n"); |
583 } | 583 } |
584 if (!b || | 584 if (!b || |
585 !load_gammas(&gamma.fVec[2], 1, b->addr((const uint8_t*) bas
e), b->fLength)) | 585 !load_gammas(&gamma.fVec[2], 1, b->addr((const uint8_t*) bas
e), b->fLength)) |
586 { | 586 { |
587 SkColorSpacePrintf("Failed to read B gamma tag.\n"); | 587 SkColorSpacePrintf("Failed to read B gamma tag.\n"); |
588 } | 588 } |
589 return SkColorSpace::NewRGB(toXYZ, gamma); | 589 |
| 590 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); |
| 591 mat.set3x3ColMajorf(toXYZ); |
| 592 return SkColorSpace::NewRGB(mat, gamma); |
590 } | 593 } |
591 | 594 |
592 // Recognize color profile specified by A2B0 tag. | 595 // Recognize color profile specified by A2B0 tag. |
593 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); | 596 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); |
594 if (a2b0) { | 597 if (a2b0) { |
595 SkColorLookUpTable colorLUT; | 598 SkColorLookUpTable colorLUT; |
596 SkFloat3 gamma; | 599 SkFloat3 gamma; |
597 SkFloat3x3 toXYZ; | 600 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); |
598 SkFloat3 toXYZOffset; | 601 if (!load_a2b0(&colorLUT, &gamma, &toXYZ, a2b0->addr((const uint
8_t*) base), |
599 if (!load_a2b0(&colorLUT, &gamma, &toXYZ, &toXYZOffset, | 602 a2b0->fLength)) { |
600 a2b0->addr((const uint8_t*) base), a2b0->fLength)) { | |
601 return_null("Failed to parse A2B0 tag"); | 603 return_null("Failed to parse A2B0 tag"); |
602 } | 604 } |
603 | 605 |
604 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
gamma, toXYZ, | 606 return sk_sp<SkColorSpace>(new SkColorSpace(std::move(colorLUT),
gamma, toXYZ)); |
605 toXYZOffset)); | |
606 } | 607 } |
607 | 608 |
608 } | 609 } |
609 default: | 610 default: |
610 break; | 611 break; |
611 } | 612 } |
612 | 613 |
613 return_null("ICC profile contains unsupported colorspace"); | 614 return_null("ICC profile contains unsupported colorspace"); |
614 } | 615 } |
OLD | NEW |