Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: src/core/SkColorSpace.cpp

Issue 2067833003: Differentiate between sRGBGamma and 2Dot2Gamma (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix DefaultXform Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/codec/SkPngCodec.cpp ('k') | src/core/SkColorSpaceXform.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "SkOnce.h" 11 #include "SkOnce.h"
12 12
13 #define SkColorSpacePrintf(...)
14
13 static bool color_space_almost_equal(float a, float b) { 15 static bool color_space_almost_equal(float a, float b) {
14 return SkTAbs(a - b) < 0.01f; 16 return SkTAbs(a - b) < 0.01f;
15 } 17 }
16 18
17 //////////////////////////////////////////////////////////////////////////////// ////////////////// 19 //////////////////////////////////////////////////////////////////////////////// //////////////////
18 20
19 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na med named) 21 SkColorSpace::SkColorSpace(GammaNamed gammaNamed, const SkMatrix44& toXYZD50, Na med named)
20 : fGammaNamed(gammaNamed) 22 : fGammaNamed(gammaNamed)
21 , fToXYZD50(toXYZD50) 23 , fToXYZD50(toXYZD50)
22 , fNamed(named) 24 , fNamed(named)
23 {} 25 {}
24 26
25 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, const SkMatrix44& t oXYZD50, 27 SkColorSpace_Base::SkColorSpace_Base(GammaNamed gammaNamed, const SkMatrix44& to XYZD50, Named named,
26 Named named, sk_sp<SkData> profileData) 28 sk_sp<SkData> profileData)
27 : INHERITED(kNonStandard_GammaNamed, toXYZD50, named) 29 : INHERITED(gammaNamed, toXYZD50, named)
28 , fGammas(std::move(gammas)) 30 , fGammas(nullptr)
29 , fProfileData(std::move(profileData)) 31 , fProfileData(std::move(profileData))
30 {} 32 {}
31 33
32 SkColorSpace_Base::SkColorSpace_Base(sk_sp<SkGammas> gammas, GammaNamed gammaNam ed,
33 const SkMatrix44& toXYZD50, Named named,
34 sk_sp<SkData> profileData)
35 : INHERITED(gammaNamed, toXYZD50, named)
36 , fGammas(std::move(gammas))
37 , fProfileData(std::move(profileData))
38 {}
39
40 SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGamma s> gammas, 34 SkColorSpace_Base::SkColorSpace_Base(SkColorLookUpTable* colorLUT, sk_sp<SkGamma s> gammas,
41 const SkMatrix44& toXYZD50, sk_sp<SkData> p rofileData) 35 const SkMatrix44& toXYZD50, sk_sp<SkData> p rofileData)
42 : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named) 36 : INHERITED(kNonStandard_GammaNamed, toXYZD50, kUnknown_Named)
43 , fColorLUT(colorLUT) 37 , fColorLUT(colorLUT)
44 , fGammas(std::move(gammas)) 38 , fGammas(std::move(gammas))
45 , fProfileData(std::move(profileData)) 39 , fProfileData(std::move(profileData))
46 {} 40 {}
47 41
48 static constexpr float gSRGB_toXYZD50[] { 42 static constexpr float gSRGB_toXYZD50[] {
49 0.4358f, 0.2224f, 0.0139f, // * R 43 0.4358f, 0.2224f, 0.0139f, // * R
(...skipping 25 matching lines...) Expand all
75 color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) && 69 color_space_almost_equal(toXYZD50.getFloat(2, 2), standard[8]) &&
76 color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) && 70 color_space_almost_equal(toXYZD50.getFloat(0, 3), 0.0f) &&
77 color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) && 71 color_space_almost_equal(toXYZD50.getFloat(1, 3), 0.0f) &&
78 color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) && 72 color_space_almost_equal(toXYZD50.getFloat(2, 3), 0.0f) &&
79 color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) && 73 color_space_almost_equal(toXYZD50.getFloat(3, 0), 0.0f) &&
80 color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) && 74 color_space_almost_equal(toXYZD50.getFloat(3, 1), 0.0f) &&
81 color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) && 75 color_space_almost_equal(toXYZD50.getFloat(3, 2), 0.0f) &&
82 color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f); 76 color_space_almost_equal(toXYZD50.getFloat(3, 3), 1.0f);
83 } 77 }
84 78
85 static SkOnce g2Dot2CurveGammasOnce; 79 static void set_gamma_value(SkGammaCurve* gamma, float value) {
86 static SkGammas* g2Dot2CurveGammas; 80 if (color_space_almost_equal(2.2f, value)) {
87 static SkOnce gLinearGammasOnce; 81 gamma->fNamed = SkColorSpace::k2Dot2Curve_GammaNamed;
88 static SkGammas* gLinearGammas; 82 } else if (color_space_almost_equal(1.0f, value)) {
89 83 gamma->fNamed = SkColorSpace::kLinear_GammaNamed;
90 sk_sp<SkColorSpace> SkColorSpace::NewRGB(const float gammaVals[3], const SkMatri x44& toXYZD50) { 84 } else if (color_space_almost_equal(0.0f, value)) {
91 return SkColorSpace_Base::NewRGB(gammaVals, toXYZD50, nullptr); 85 SkColorSpacePrintf("Treating invalid zero gamma as linear.");
86 gamma->fNamed = SkColorSpace::kLinear_GammaNamed;
87 } else {
88 gamma->fValue = value;
89 }
92 } 90 }
93 91
94 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(const float gammaVals[3], const Sk Matrix44& toXYZD50, 92 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(float values[3], const SkMatrix44& toXYZD50) {
95 sk_sp<SkData> profileData) { 93 SkGammaCurve curves[3];
96 sk_sp<SkGammas> gammas = nullptr; 94 set_gamma_value(&curves[0], values[0]);
97 GammaNamed gammaNamed = kNonStandard_GammaNamed; 95 set_gamma_value(&curves[1], values[1]);
96 set_gamma_value(&curves[2], values[2]);
98 97
99 // Check if we really have sRGB or Adobe RGB 98 GammaNamed gammaNamed = SkGammas::Named(curves);
100 if (color_space_almost_equal(2.2f, gammaVals[0]) && 99 if (kNonStandard_GammaNamed == gammaNamed) {
101 color_space_almost_equal(2.2f, gammaVals[1]) && 100 sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::move(curv es[1]),
102 color_space_almost_equal(2.2f, gammaVals[2])) 101 std::move(curves[2])));
103 { 102 return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, gammas, toXYZD 50, nullptr));
104 g2Dot2CurveGammasOnce([] {
105 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
106 });
107 gammas = sk_ref_sp(g2Dot2CurveGammas);
108 gammaNamed = k2Dot2Curve_GammaNamed;
109
110 if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
111 return SkColorSpace::NewNamed(kSRGB_Named);
112 } else if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) {
113 return SkColorSpace::NewNamed(kAdobeRGB_Named);
114 }
115 } else if (color_space_almost_equal(1.0f, gammaVals[0]) &&
116 color_space_almost_equal(1.0f, gammaVals[1]) &&
117 color_space_almost_equal(1.0f, gammaVals[2]))
118 {
119 gLinearGammasOnce([] {
120 gLinearGammas = new SkGammas(1.0f, 1.0f, 1.0f);
121 });
122 gammas = sk_ref_sp(gLinearGammas);
123 gammaNamed = kLinear_GammaNamed;
124 } 103 }
125 104
126 if (!gammas) { 105 return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr);
127 gammas = sk_sp<SkGammas>(new SkGammas(gammaVals[0], gammaVals[1], gammaV als[2])); 106 }
107
108 sk_sp<SkColorSpace> SkColorSpace_Base::NewRGB(GammaNamed gammaNamed, const SkMat rix44& toXYZD50,
109 sk_sp<SkData> profileData) {
110 switch (gammaNamed) {
111 case kSRGB_GammaNamed:
112 if (xyz_almost_equal(toXYZD50, gSRGB_toXYZD50)) {
113 return SkColorSpace::NewNamed(kSRGB_Named);
114 }
115 break;
116 case k2Dot2Curve_GammaNamed:
117 if (xyz_almost_equal(toXYZD50, gAdobeRGB_toXYZD50)) {
118 return SkColorSpace::NewNamed(kAdobeRGB_Named);
119 }
120 break;
121 case kNonStandard_GammaNamed:
122 // This is not allowed.
123 return nullptr;
124 default:
125 break;
128 } 126 }
129 return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammas, gammaNamed, toXYZD5 0, kUnknown_Named, 127
130 std::move(profileData))); 128 return sk_sp<SkColorSpace>(new SkColorSpace_Base(gammaNamed, toXYZD50, kUnkn own_Named,
129 profileData));
130 }
131
132 sk_sp<SkColorSpace> SkColorSpace::NewRGB(GammaNamed gammaNamed, const SkMatrix44 & toXYZD50) {
133 return SkColorSpace_Base::NewRGB(gammaNamed, toXYZD50, nullptr);
131 } 134 }
132 135
133 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) { 136 sk_sp<SkColorSpace> SkColorSpace::NewNamed(Named named) {
134 static SkOnce sRGBOnce; 137 static SkOnce sRGBOnce;
135 static SkColorSpace* sRGB; 138 static SkColorSpace* sRGB;
136 static SkOnce adobeRGBOnce; 139 static SkOnce adobeRGBOnce;
137 static SkColorSpace* adobeRGB; 140 static SkColorSpace* adobeRGB;
138 141
139 switch (named) { 142 switch (named) {
140 case kSRGB_Named: { 143 case kSRGB_Named: {
141 g2Dot2CurveGammasOnce([] {
142 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
143 });
144
145 sRGBOnce([] { 144 sRGBOnce([] {
146 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor); 145 SkMatrix44 srgbToxyzD50(SkMatrix44::kUninitialized_Constructor);
147 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50); 146 srgbToxyzD50.set3x3ColMajorf(gSRGB_toXYZD50);
148 sRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas), k2Dot 2Curve_GammaNamed, 147 sRGB = new SkColorSpace_Base(kSRGB_GammaNamed, srgbToxyzD50, kSR GB_Named, nullptr);
149 srgbToxyzD50, kSRGB_Named, nullptr) ;
150 }); 148 });
151 return sk_ref_sp(sRGB); 149 return sk_ref_sp(sRGB);
152 } 150 }
153 case kAdobeRGB_Named: { 151 case kAdobeRGB_Named: {
154 g2Dot2CurveGammasOnce([] {
155 g2Dot2CurveGammas = new SkGammas(2.2f, 2.2f, 2.2f);
156 });
157
158 adobeRGBOnce([] { 152 adobeRGBOnce([] {
159 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct or); 153 SkMatrix44 adobergbToxyzD50(SkMatrix44::kUninitialized_Construct or);
160 adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50); 154 adobergbToxyzD50.set3x3ColMajorf(gAdobeRGB_toXYZD50);
161 adobeRGB = new SkColorSpace_Base(sk_ref_sp(g2Dot2CurveGammas), 155 adobeRGB = new SkColorSpace_Base(k2Dot2Curve_GammaNamed, adoberg bToxyzD50,
162 k2Dot2Curve_GammaNamed, adoberg bToxyzD50,
163 kAdobeRGB_Named, nullptr); 156 kAdobeRGB_Named, nullptr);
164 }); 157 });
165 return sk_ref_sp(adobeRGB); 158 return sk_ref_sp(adobeRGB);
166 } 159 }
167 default: 160 default:
168 break; 161 break;
169 } 162 }
170 return nullptr; 163 return nullptr;
171 } 164 }
172 165
173 //////////////////////////////////////////////////////////////////////////////// /////////////////// 166 //////////////////////////////////////////////////////////////////////////////// ///////////////////
174 167
175 #include "SkFixed.h" 168 #include "SkFixed.h"
176 #include "SkTemplates.h" 169 #include "SkTemplates.h"
177 170
178 #define SkColorSpacePrintf(...)
179
180 #define return_if_false(pred, msg) \ 171 #define return_if_false(pred, msg) \
181 do { \ 172 do { \
182 if (!(pred)) { \ 173 if (!(pred)) { \
183 SkColorSpacePrintf("Invalid ICC Profile: %s.\n", (msg)); \ 174 SkColorSpacePrintf("Invalid ICC Profile: %s.\n", (msg)); \
184 return false; \ 175 return false; \
185 } \ 176 } \
186 } while (0) 177 } while (0)
187 178
188 #define return_null(msg) \ 179 #define return_null(msg) \
189 do { \ 180 do { \
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 }; 354 };
364 355
365 static constexpr uint32_t kTAG_rXYZ = SkSetFourByteTag('r', 'X', 'Y', 'Z'); 356 static constexpr uint32_t kTAG_rXYZ = SkSetFourByteTag('r', 'X', 'Y', 'Z');
366 static constexpr uint32_t kTAG_gXYZ = SkSetFourByteTag('g', 'X', 'Y', 'Z'); 357 static constexpr uint32_t kTAG_gXYZ = SkSetFourByteTag('g', 'X', 'Y', 'Z');
367 static constexpr uint32_t kTAG_bXYZ = SkSetFourByteTag('b', 'X', 'Y', 'Z'); 358 static constexpr uint32_t kTAG_bXYZ = SkSetFourByteTag('b', 'X', 'Y', 'Z');
368 static constexpr uint32_t kTAG_rTRC = SkSetFourByteTag('r', 'T', 'R', 'C'); 359 static constexpr uint32_t kTAG_rTRC = SkSetFourByteTag('r', 'T', 'R', 'C');
369 static constexpr uint32_t kTAG_gTRC = SkSetFourByteTag('g', 'T', 'R', 'C'); 360 static constexpr uint32_t kTAG_gTRC = SkSetFourByteTag('g', 'T', 'R', 'C');
370 static constexpr uint32_t kTAG_bTRC = SkSetFourByteTag('b', 'T', 'R', 'C'); 361 static constexpr uint32_t kTAG_bTRC = SkSetFourByteTag('b', 'T', 'R', 'C');
371 static constexpr uint32_t kTAG_A2B0 = SkSetFourByteTag('A', '2', 'B', '0'); 362 static constexpr uint32_t kTAG_A2B0 = SkSetFourByteTag('A', '2', 'B', '0');
372 363
373 bool load_xyz(float dst[3], const uint8_t* src, size_t len) { 364 static bool load_xyz(float dst[3], const uint8_t* src, size_t len) {
374 if (len < 20) { 365 if (len < 20) {
375 SkColorSpacePrintf("XYZ tag is too small (%d bytes)", len); 366 SkColorSpacePrintf("XYZ tag is too small (%d bytes)", len);
376 return false; 367 return false;
377 } 368 }
378 369
379 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8)); 370 dst[0] = SkFixedToFloat(read_big_endian_int(src + 8));
380 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12)); 371 dst[1] = SkFixedToFloat(read_big_endian_int(src + 12));
381 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16)); 372 dst[2] = SkFixedToFloat(read_big_endian_int(src + 16));
382 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]); 373 SkColorSpacePrintf("XYZ %g %g %g\n", dst[0], dst[1], dst[2]);
383 return true; 374 return true;
384 } 375 }
385 376
386 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', ' v'); 377 static constexpr uint32_t kTAG_CurveType = SkSetFourByteTag('c', 'u', 'r', ' v');
387 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', ' a'); 378 static constexpr uint32_t kTAG_ParaCurveType = SkSetFourByteTag('p', 'a', 'r', ' a');
388 379
389 bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, s ize_t len) { 380 static bool load_gammas(SkGammaCurve* gammas, uint32_t numGammas, const uint8_t* src, size_t len) {
390 for (uint32_t i = 0; i < numGammas; i++) { 381 for (uint32_t i = 0; i < numGammas; i++) {
391 if (len < 12) { 382 if (len < 12) {
392 // FIXME (msarett): 383 // FIXME (msarett):
393 // We could potentially return false here after correctly parsing *s ome* of the 384 // We could potentially return false here after correctly parsing *s ome* of the
394 // gammas correctly. Should we somehow try to indicate a partial su ccess? 385 // gammas correctly. Should we somehow try to indicate a partial su ccess?
395 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); 386 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
396 return false; 387 return false;
397 } 388 }
398 389
399 // We need to count the number of bytes in the tag, so we are able to mo ve to the 390 // We need to count the number of bytes in the tag, so we are able to mo ve to the
(...skipping 11 matching lines...) Expand all
411 !safe_add((size_t) 12, tagBytes, &tagBytes)) 402 !safe_add((size_t) 12, tagBytes, &tagBytes))
412 { 403 {
413 SkColorSpacePrintf("Invalid gamma count"); 404 SkColorSpacePrintf("Invalid gamma count");
414 return false; 405 return false;
415 } 406 }
416 407
417 if (0 == count) { 408 if (0 == count) {
418 // Some tags require a gamma curve, but the author doesn't a ctually want 409 // Some tags require a gamma curve, but the author doesn't a ctually want
419 // to transform the data. In this case, it is common to see a curve with 410 // to transform the data. In this case, it is common to see a curve with
420 // a count of 0. 411 // a count of 0.
421 gammas[i].fValue = 1.0f; 412 gammas[i].fNamed = SkColorSpace::kLinear_GammaNamed;
422 break; 413 break;
423 } else if (len < tagBytes) { 414 } else if (len < tagBytes) {
424 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len) ; 415 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len) ;
425 return false; 416 return false;
426 } 417 }
427 418
428 const uint16_t* table = (const uint16_t*) (src + 12); 419 const uint16_t* table = (const uint16_t*) (src + 12);
429 if (1 == count) { 420 if (1 == count) {
430 // The table entry is the gamma (with a bias of 256). 421 // The table entry is the gamma (with a bias of 256).
431 uint16_t value = read_big_endian_short((const uint8_t*) tabl e); 422 float value = (read_big_endian_short((const uint8_t*) table) ) / 256.0f;
432 gammas[i].fValue = value / 256.0f; 423 set_gamma_value(&gammas[i], value);
433 if (0.0f == gammas[i].fValue) { 424 SkColorSpacePrintf("gamma %g\n", value);
434 SkColorSpacePrintf("Cannot have zero gamma value");
435 return false;
436 }
437 SkColorSpacePrintf("gamma %d %g\n", value, gammas[i].fValue) ;
438 break; 425 break;
439 } 426 }
440 427
441 // Check for frequently occurring curves and use a fast approxim ation. 428 // Check for frequently occurring sRGB curves.
442 // We do this by sampling a few values and see if they match our expectation. 429 // We do this by sampling a few values and see if they match our expectation.
443 // A more robust solution would be to compare each value in this curve against 430 // A more robust solution would be to compare each value in this curve against
444 // a 2.2f curve see if we remain below an error threshold. At t his time, 431 // an sRGB curve to see if we remain below an error threshold. At this time,
445 // we haven't seen any images in the wild that make this kind of 432 // we haven't seen any images in the wild that make this kind of
446 // calculation necessary. We encounter identical gamma curves o ver and 433 // calculation necessary. We encounter identical gamma curves o ver and
447 // over again, but relatively few variations. 434 // over again, but relatively few variations.
448 if (1024 == count) { 435 if (1024 == count) {
449 // The magic values were chosen because they match a very co mmon sRGB 436 // The magic values were chosen because they match a very co mmon sRGB
450 // gamma table and the less common Canon sRGB gamma table (w hich use 437 // gamma table and the less common Canon sRGB gamma table (w hich use
451 // different rounding rules). 438 // different rounding rules).
452 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & & 439 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & &
453 3366 == read_big_endian_short((const uint8_t*) &tabl e[257]) && 440 3366 == read_big_endian_short((const uint8_t*) &tabl e[257]) &&
454 14116 == read_big_endian_short((const uint8_t*) &tab le[513]) && 441 14116 == read_big_endian_short((const uint8_t*) &tab le[513]) &&
455 34318 == read_big_endian_short((const uint8_t*) &tab le[768]) && 442 34318 == read_big_endian_short((const uint8_t*) &tab le[768]) &&
456 65535 == read_big_endian_short((const uint8_t*) &tab le[1023])) { 443 65535 == read_big_endian_short((const uint8_t*) &tab le[1023])) {
457 gammas[i].fValue = 2.2f; 444 gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed;
458 break; 445 break;
459 } 446 }
460 } else if (26 == count) { 447 } else if (26 == count) {
461 // The magic values were chosen because they match a very co mmon sRGB 448 // The magic values were chosen because they match a very co mmon sRGB
462 // gamma table. 449 // gamma table.
463 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & & 450 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & &
464 3062 == read_big_endian_short((const uint8_t*) &tabl e[6]) && 451 3062 == read_big_endian_short((const uint8_t*) &tabl e[6]) &&
465 12824 == read_big_endian_short((const uint8_t*) &tab le[12]) && 452 12824 == read_big_endian_short((const uint8_t*) &tab le[12]) &&
466 31237 == read_big_endian_short((const uint8_t*) &tab le[18]) && 453 31237 == read_big_endian_short((const uint8_t*) &tab le[18]) &&
467 65535 == read_big_endian_short((const uint8_t*) &tab le[25])) { 454 65535 == read_big_endian_short((const uint8_t*) &tab le[25])) {
468 gammas[i].fValue = 2.2f; 455 gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed;
469 break; 456 break;
470 } 457 }
471 } else if (4096 == count) { 458 } else if (4096 == count) {
472 // The magic values were chosen because they match Nikon, Ep son, and 459 // The magic values were chosen because they match Nikon, Ep son, and
473 // LCMS sRGB gamma tables (all of which use different roundi ng rules). 460 // LCMS sRGB gamma tables (all of which use different roundi ng rules).
474 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & & 461 if (0 == read_big_endian_short((const uint8_t*) &table[0]) & &
475 950 == read_big_endian_short((const uint8_t*) &table [515]) && 462 950 == read_big_endian_short((const uint8_t*) &table [515]) &&
476 3342 == read_big_endian_short((const uint8_t*) &tabl e[1025]) && 463 3342 == read_big_endian_short((const uint8_t*) &tabl e[1025]) &&
477 14079 == read_big_endian_short((const uint8_t*) &tab le[2051]) && 464 14079 == read_big_endian_short((const uint8_t*) &tab le[2051]) &&
478 65535 == read_big_endian_short((const uint8_t*) &tab le[4095])) { 465 65535 == read_big_endian_short((const uint8_t*) &tab le[4095])) {
479 gammas[i].fValue = 2.2f; 466 gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed;
480 break; 467 break;
481 } 468 }
482 } 469 }
483 470
484 // Otherwise, fill in the interpolation table. 471 // Otherwise, fill in the interpolation table.
485 gammas[i].fTableSize = count; 472 gammas[i].fTableSize = count;
486 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]); 473 gammas[i].fTable = std::unique_ptr<float[]>(new float[count]);
487 for (uint32_t j = 0; j < count; j++) { 474 for (uint32_t j = 0; j < count; j++) {
488 gammas[i].fTable[j] = 475 gammas[i].fTable[j] =
489 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f; 476 (read_big_endian_short((const uint8_t*) &table[j])) / 65535.0f;
(...skipping 13 matching lines...) Expand all
503 uint16_t format = read_big_endian_short(src + 8); 490 uint16_t format = read_big_endian_short(src + 8);
504 if (kExponential_ParaCurveType == format) { 491 if (kExponential_ParaCurveType == format) {
505 tagBytes = 12 + 4; 492 tagBytes = 12 + 4;
506 if (len < tagBytes) { 493 if (len < tagBytes) {
507 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len); 494 SkColorSpacePrintf("gamma tag is too small (%d bytes)", len);
508 return false; 495 return false;
509 } 496 }
510 497
511 // Y = X^g 498 // Y = X^g
512 int32_t g = read_big_endian_int(src + 12); 499 int32_t g = read_big_endian_int(src + 12);
513 gammas[i].fValue = SkFixedToFloat(g); 500 set_gamma_value(&gammas[i], SkFixedToFloat(g));
514 } else { 501 } else {
515 // Here's where the real parametric gammas start. There are many 502 // Here's where the real parametric gammas start. There are many
516 // permutations of the same equations. 503 // permutations of the same equations.
517 // 504 //
518 // Y = (aX + b)^g + c for X >= d 505 // Y = (aX + b)^g + c for X >= d
519 // Y = eX + f otherwise 506 // Y = eX + f otherwise
520 // 507 //
521 // We will fill in with zeros as necessary to always match t he above form. 508 // We will fill in with zeros as necessary to always match t he above form.
522 float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 0.0f, f = 0.0f; 509 float g = 0.0f, a = 0.0f, b = 0.0f, c = 0.0f, d = 0.0f, e = 0.0f, f = 0.0f;
523 switch(format) { 510 switch(format) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 } 587 }
601 588
602 // Recognize and simplify a very common parametric represent ation of sRGB gamma. 589 // Recognize and simplify a very common parametric represent ation of sRGB gamma.
603 if (color_space_almost_equal(0.9479f, a) && 590 if (color_space_almost_equal(0.9479f, a) &&
604 color_space_almost_equal(0.0521f, b) && 591 color_space_almost_equal(0.0521f, b) &&
605 color_space_almost_equal(0.0000f, c) && 592 color_space_almost_equal(0.0000f, c) &&
606 color_space_almost_equal(0.0405f, d) && 593 color_space_almost_equal(0.0405f, d) &&
607 color_space_almost_equal(0.0774f, e) && 594 color_space_almost_equal(0.0774f, e) &&
608 color_space_almost_equal(0.0000f, f) && 595 color_space_almost_equal(0.0000f, f) &&
609 color_space_almost_equal(2.4000f, g)) { 596 color_space_almost_equal(2.4000f, g)) {
610 gammas[i].fValue = 2.2f; 597 gammas[i].fNamed = SkColorSpace::kSRGB_GammaNamed;
611 } else { 598 } else {
612 // Fail on invalid gammas. 599 // Fail on invalid gammas.
613 if (d <= 0.0f) { 600 if (d <= 0.0f) {
614 // Y = (aX + b)^g + c for always 601 // Y = (aX + b)^g + c for always
615 if (0.0f == a || 0.0f == g) { 602 if (0.0f == a || 0.0f == g) {
616 SkColorSpacePrintf("A or G is zero, constant gam ma function " 603 SkColorSpacePrintf("A or G is zero, constant gam ma function "
617 "is nonsense"); 604 "is nonsense");
618 return false; 605 return false;
619 } 606 }
620 } else if (d >= 1.0f) { 607 } else if (d >= 1.0f) {
(...skipping 20 matching lines...) Expand all
641 } 628 }
642 629
643 break; 630 break;
644 } 631 }
645 default: 632 default:
646 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type); 633 SkColorSpacePrintf("Unsupported gamma tag type %d\n", type);
647 return false; 634 return false;
648 } 635 }
649 636
650 // Ensure that we have successfully read a gamma representation. 637 // Ensure that we have successfully read a gamma representation.
651 SkASSERT(gammas[i].isValue() || gammas[i].isTable() || gammas[i].isParam etric()); 638 SkASSERT(gammas[i].isNamed() || gammas[i].isValue() || gammas[i].isTable () ||
639 gammas[i].isParametric());
652 640
653 // Adjust src and len if there is another gamma curve to load. 641 // Adjust src and len if there is another gamma curve to load.
654 if (i != numGammas - 1) { 642 if (i != numGammas - 1) {
655 // Each curve is padded to 4-byte alignment. 643 // Each curve is padded to 4-byte alignment.
656 tagBytes = SkAlign4(tagBytes); 644 tagBytes = SkAlign4(tagBytes);
657 if (len < tagBytes) { 645 if (len < tagBytes) {
658 return false; 646 return false;
659 } 647 }
660 648
661 src += tagBytes; 649 src += tagBytes;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 if (0 != offsetToColorLUT && offsetToColorLUT < len) { 777 if (0 != offsetToColorLUT && offsetToColorLUT < len) {
790 if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offse tToColorLUT, 778 if (!load_color_lut(colorLUT, inputChannels, outputChannels, src + offse tToColorLUT,
791 len - offsetToColorLUT)) { 779 len - offsetToColorLUT)) {
792 SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n"); 780 SkColorSpacePrintf("Failed to read color LUT from A to B tag.\n");
793 } 781 }
794 } 782 }
795 783
796 uint32_t offsetToMCurves = read_big_endian_int(src + 20); 784 uint32_t offsetToMCurves = read_big_endian_int(src + 20);
797 if (0 != offsetToMCurves && offsetToMCurves < len) { 785 if (0 != offsetToMCurves && offsetToMCurves < len) {
798 if (!load_gammas(gammas, outputChannels, src + offsetToMCurves, len - of fsetToMCurves)) { 786 if (!load_gammas(gammas, outputChannels, src + offsetToMCurves, len - of fsetToMCurves)) {
799 SkColorSpacePrintf("Failed to read M curves from A to B tag.\n"); 787 SkColorSpacePrintf("Failed to read M curves from A to B tag. Using linear gamma.\n");
788 gammas[0].fNamed = SkColorSpace::kLinear_GammaNamed;
789 gammas[1].fNamed = SkColorSpace::kLinear_GammaNamed;
790 gammas[2].fNamed = SkColorSpace::kLinear_GammaNamed;
800 } 791 }
801 } 792 }
802 793
803 uint32_t offsetToMatrix = read_big_endian_int(src + 16); 794 uint32_t offsetToMatrix = read_big_endian_int(src + 16);
804 if (0 != offsetToMatrix && offsetToMatrix < len) { 795 if (0 != offsetToMatrix && offsetToMatrix < len) {
805 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) { 796 if (!load_matrix(toXYZ, src + offsetToMatrix, len - offsetToMatrix)) {
806 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n"); 797 SkColorSpacePrintf("Failed to read matrix from A to B tag.\n");
798 toXYZ->setIdentity();
807 } 799 }
808 } 800 }
809 801
810 return true; 802 return true;
811 } 803 }
812 804
813 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) { 805 sk_sp<SkColorSpace> SkColorSpace::NewICC(const void* input, size_t len) {
814 if (!input || len < kICCHeaderSize) { 806 if (!input || len < kICCHeaderSize) {
815 return_null("Data is null or not large enough to contain an ICC profile" ); 807 return_null("Data is null or not large enough to contain an ICC profile" );
816 } 808 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ); 857 const ICCTag* g = ICCTag::Find(tags.get(), tagCount, kTAG_gXYZ);
866 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ); 858 const ICCTag* b = ICCTag::Find(tags.get(), tagCount, kTAG_bXYZ);
867 if (r && g && b) { 859 if (r && g && b) {
868 float toXYZ[9]; 860 float toXYZ[9];
869 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen gth) || 861 if (!load_xyz(&toXYZ[0], r->addr((const uint8_t*) base), r->fLen gth) ||
870 !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen gth) || 862 !load_xyz(&toXYZ[3], g->addr((const uint8_t*) base), g->fLen gth) ||
871 !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen gth)) 863 !load_xyz(&toXYZ[6], b->addr((const uint8_t*) base), b->fLen gth))
872 { 864 {
873 return_null("Need valid rgb tags for XYZ space"); 865 return_null("Need valid rgb tags for XYZ space");
874 } 866 }
867 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor);
868 mat.set3x3ColMajorf(toXYZ);
875 869
876 // It is not uncommon to see missing or empty gamma tags. This indicates 870 // It is not uncommon to see missing or empty gamma tags. This indicates
877 // that we should use unit gamma. 871 // that we should use unit gamma.
878 SkGammaCurve curves[3]; 872 SkGammaCurve curves[3];
879 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC); 873 r = ICCTag::Find(tags.get(), tagCount, kTAG_rTRC);
880 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC); 874 g = ICCTag::Find(tags.get(), tagCount, kTAG_gTRC);
881 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC); 875 b = ICCTag::Find(tags.get(), tagCount, kTAG_bTRC);
882 if (!r || !load_gammas(&curves[0], 1, r->addr((const uint8_t*) b ase), r->fLength)) 876 if (!r || !load_gammas(&curves[0], 1, r->addr((const uint8_t*) b ase), r->fLength))
883 { 877 {
884 SkColorSpacePrintf("Failed to read R gamma tag.\n"); 878 SkColorSpacePrintf("Failed to read R gamma tag.\n");
879 curves[0].fNamed = SkColorSpace::kLinear_GammaNamed;
885 } 880 }
886 if (!g || !load_gammas(&curves[1], 1, g->addr((const uint8_t*) b ase), g->fLength)) 881 if (!g || !load_gammas(&curves[1], 1, g->addr((const uint8_t*) b ase), g->fLength))
887 { 882 {
888 SkColorSpacePrintf("Failed to read G gamma tag.\n"); 883 SkColorSpacePrintf("Failed to read G gamma tag.\n");
884 curves[1].fNamed = SkColorSpace::kLinear_GammaNamed;
889 } 885 }
890 if (!b || !load_gammas(&curves[2], 1, b->addr((const uint8_t*) b ase), b->fLength)) 886 if (!b || !load_gammas(&curves[2], 1, b->addr((const uint8_t*) b ase), b->fLength))
891 { 887 {
892 SkColorSpacePrintf("Failed to read B gamma tag.\n"); 888 SkColorSpacePrintf("Failed to read B gamma tag.\n");
889 curves[2].fNamed = SkColorSpace::kLinear_GammaNamed;
893 } 890 }
894 891
895 sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::m ove(curves[1]), 892 GammaNamed gammaNamed = SkGammas::Named(curves);
896 std::move(curves[2]))); 893 if (kNonStandard_GammaNamed == gammaNamed) {
897 SkMatrix44 mat(SkMatrix44::kUninitialized_Constructor); 894 sk_sp<SkGammas> gammas = sk_make_sp<SkGammas>(std::move(curv es[0]),
898 mat.set3x3ColMajorf(toXYZ); 895 std::move(curv es[1]),
899 if (gammas->isValues()) { 896 std::move(curv es[2]));
900 // When we have values, take advantage of the NewFromRGB ini tializer. 897 return sk_sp<SkColorSpace>(new SkColorSpace_Base(nullptr, st d::move(gammas),
901 // This allows us to check for canonical sRGB and Adobe RGB. 898 mat, std::m ove(data)));
902 float gammaVals[3];
903 gammaVals[0] = gammas->fRed.fValue;
904 gammaVals[1] = gammas->fGreen.fValue;
905 gammaVals[2] = gammas->fBlue.fValue;
906 return SkColorSpace_Base::NewRGB(gammaVals, mat, std::move(d ata));
907 } else { 899 } else {
908 return sk_sp<SkColorSpace>(new SkColorSpace_Base(std::move(g ammas), mat, 900 return SkColorSpace_Base::NewRGB(gammaNamed, mat, std::move( data));
909 kUnknown_Na med,
910 std::move(d ata)));
911 } 901 }
912 } 902 }
913 903
914 // Recognize color profile specified by A2B0 tag. 904 // Recognize color profile specified by A2B0 tag.
915 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0); 905 const ICCTag* a2b0 = ICCTag::Find(tags.get(), tagCount, kTAG_A2B0);
916 if (a2b0) { 906 if (a2b0) {
917 SkAutoTDelete<SkColorLookUpTable> colorLUT(new SkColorLookUpTabl e()); 907 SkAutoTDelete<SkColorLookUpTable> colorLUT(new SkColorLookUpTabl e());
918 SkGammaCurve curves[3]; 908 SkGammaCurve curves[3];
919 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor); 909 SkMatrix44 toXYZ(SkMatrix44::kUninitialized_Constructor);
920 if (!load_a2b0(colorLUT, curves, &toXYZ, a2b0->addr((const uint8 _t*) base), 910 if (!load_a2b0(colorLUT, curves, &toXYZ, a2b0->addr((const uint8 _t*) base),
921 a2b0->fLength)) { 911 a2b0->fLength)) {
922 return_null("Failed to parse A2B0 tag"); 912 return_null("Failed to parse A2B0 tag");
923 } 913 }
924 914
925 sk_sp<SkGammas> gammas(new SkGammas(std::move(curves[0]), std::m ove(curves[1]), 915 GammaNamed gammaNamed = SkGammas::Named(curves);
926 std::move(curves[2]))); 916 if (colorLUT->fTable || kNonStandard_GammaNamed == gammaNamed) {
927 if (colorLUT->fTable) { 917 sk_sp<SkGammas> gammas = sk_make_sp<SkGammas>(std::move(curv es[0]),
918 std::move(curv es[1]),
919 std::move(curv es[2]));
920
928 return sk_sp<SkColorSpace>(new SkColorSpace_Base(colorLUT.re lease(), 921 return sk_sp<SkColorSpace>(new SkColorSpace_Base(colorLUT.re lease(),
929 std::move(g ammas), toXYZ, 922 std::move(g ammas), toXYZ,
930 std::move(d ata))); 923 std::move(d ata)));
931 } else if (gammas->isValues()) {
932 // When we have values, take advantage of the NewFromRGB ini tializer.
933 // This allows us to check for canonical sRGB and Adobe RGB.
934 float gammaVals[3];
935 gammaVals[0] = gammas->fRed.fValue;
936 gammaVals[1] = gammas->fGreen.fValue;
937 gammaVals[2] = gammas->fBlue.fValue;
938 return SkColorSpace_Base::NewRGB(gammaVals, toXYZ, std::move (data));
939 } else { 924 } else {
940 return sk_sp<SkColorSpace>(new SkColorSpace_Base(std::move(g ammas), toXYZ, 925 return SkColorSpace_Base::NewRGB(gammaNamed, toXYZ, std::mov e(data));
941 kUnknown_Na med,
942 std::move(d ata)));
943 } 926 }
944 } 927 }
945 } 928 }
946 default: 929 default:
947 break; 930 break;
948 } 931 }
949 932
950 return_null("ICC profile contains unsupported colorspace"); 933 return_null("ICC profile contains unsupported colorspace");
951 } 934 }
952 935
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1072 ptr[2] = SkEndian_SwapBE32(1); 1055 ptr[2] = SkEndian_SwapBE32(1);
1073 1056
1074 // Convert gamma to 16-bit fixed point. 1057 // Convert gamma to 16-bit fixed point.
1075 uint16_t* ptr16 = (uint16_t*) (ptr + 3); 1058 uint16_t* ptr16 = (uint16_t*) (ptr + 3);
1076 ptr16[0] = SkEndian_SwapBE16((uint16_t) (value * 256.0f)); 1059 ptr16[0] = SkEndian_SwapBE16((uint16_t) (value * 256.0f));
1077 1060
1078 // Pad tag with zero. 1061 // Pad tag with zero.
1079 ptr16[1] = 0; 1062 ptr16[1] = 0;
1080 } 1063 }
1081 1064
1065 static float get_gamma_value(const SkGammaCurve* curve) {
1066 switch (curve->fNamed) {
1067 case SkColorSpace::kSRGB_GammaNamed:
1068 // FIXME (msarett):
1069 // kSRGB cannot be represented by a value. Here we fall through to 2.2f,
1070 // which is a close guess. To be more accurate, we need to represen t sRGB
1071 // gamma with a parametric curve.
1072 case SkColorSpace::k2Dot2Curve_GammaNamed:
1073 return 2.2f;
1074 case SkColorSpace::kLinear_GammaNamed:
1075 return 1.0f;
1076 default:
1077 SkASSERT(curve->isValue());
1078 return curve->fValue;
1079 }
1080 }
1081
1082 sk_sp<SkData> SkColorSpace_Base::writeToICC() const { 1082 sk_sp<SkData> SkColorSpace_Base::writeToICC() const {
1083 // Return if this object was created from a profile, or if we have already s erialized 1083 // Return if this object was created from a profile, or if we have already s erialized
1084 // the profile. 1084 // the profile.
1085 if (fProfileData) { 1085 if (fProfileData) {
1086 return fProfileData; 1086 return fProfileData;
1087 } 1087 }
1088 1088
1089 // The client may create an SkColorSpace using an SkMatrix44, but currently we only 1089 // The client may create an SkColorSpace using an SkMatrix44, but currently we only
1090 // support writing profiles with 3x3 matrices. 1090 // support writing profiles with 3x3 matrices.
1091 // TODO (msarett): Fix this! 1091 // TODO (msarett): Fix this!
(...skipping 21 matching lines...) Expand all
1113 1113
1114 // Write XYZ tags 1114 // Write XYZ tags
1115 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 0); 1115 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 0);
1116 ptr += kTAG_XYZ_Bytes; 1116 ptr += kTAG_XYZ_Bytes;
1117 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 1); 1117 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 1);
1118 ptr += kTAG_XYZ_Bytes; 1118 ptr += kTAG_XYZ_Bytes;
1119 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 2); 1119 write_xyz_tag((uint32_t*) ptr, fToXYZD50, 2);
1120 ptr += kTAG_XYZ_Bytes; 1120 ptr += kTAG_XYZ_Bytes;
1121 1121
1122 // Write TRC tags 1122 // Write TRC tags
1123 SkASSERT(as_CSB(this)->fGammas->fRed.isValue()); 1123 GammaNamed gammaNamed = this->gammaNamed();
1124 write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fRed.fValue); 1124 if (kNonStandard_GammaNamed == gammaNamed) {
1125 ptr += SkAlign4(kTAG_TRC_Bytes); 1125 write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f Red));
1126 SkASSERT(as_CSB(this)->fGammas->fGreen.isValue()); 1126 ptr += SkAlign4(kTAG_TRC_Bytes);
1127 write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fGreen.fValue); 1127 write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f Green));
1128 ptr += SkAlign4(kTAG_TRC_Bytes); 1128 ptr += SkAlign4(kTAG_TRC_Bytes);
1129 SkASSERT(as_CSB(this)->fGammas->fBlue.isValue()); 1129 write_trc_tag((uint32_t*) ptr, get_gamma_value(&as_CSB(this)->fGammas->f Blue));
1130 write_trc_tag((uint32_t*) ptr, as_CSB(this)->fGammas->fBlue.fValue); 1130 ptr += SkAlign4(kTAG_TRC_Bytes);
1131 ptr += SkAlign4(kTAG_TRC_Bytes); 1131 } else {
1132 switch (gammaNamed) {
1133 case SkColorSpace::kSRGB_GammaNamed:
1134 // FIXME (msarett):
1135 // kSRGB cannot be represented by a value. Here we fall through to 2.2f,
1136 // which is a close guess. To be more accurate, we need to repr esent sRGB
1137 // gamma with a parametric curve.
1138 case SkColorSpace::k2Dot2Curve_GammaNamed:
1139 write_trc_tag((uint32_t*) ptr, 2.2f);
1140 ptr += SkAlign4(kTAG_TRC_Bytes);
1141 write_trc_tag((uint32_t*) ptr, 2.2f);
1142 ptr += SkAlign4(kTAG_TRC_Bytes);
1143 write_trc_tag((uint32_t*) ptr, 2.2f);
1144 ptr += SkAlign4(kTAG_TRC_Bytes);
1145 break;
1146 case SkColorSpace::kLinear_GammaNamed:
1147 write_trc_tag((uint32_t*) ptr, 1.0f);
1148 ptr += SkAlign4(kTAG_TRC_Bytes);
1149 write_trc_tag((uint32_t*) ptr, 1.0f);
1150 ptr += SkAlign4(kTAG_TRC_Bytes);
1151 write_trc_tag((uint32_t*) ptr, 1.0f);
1152 ptr += SkAlign4(kTAG_TRC_Bytes);
1153 break;
1154 default:
1155 SkASSERT(false);
1156 break;
1157 }
1158 }
1132 1159
1133 // Write white point tag 1160 // Write white point tag
1134 uint32_t* ptr32 = (uint32_t*) ptr; 1161 uint32_t* ptr32 = (uint32_t*) ptr;
1135 ptr32[0] = SkEndian_SwapBE32(kXYZ_PCSSpace); 1162 ptr32[0] = SkEndian_SwapBE32(kXYZ_PCSSpace);
1136 ptr32[1] = 0; 1163 ptr32[1] = 0;
1137 // TODO (msarett): These values correspond to the D65 white point. This may not always be 1164 // TODO (msarett): These values correspond to the D65 white point. This may not always be
1138 // correct. 1165 // correct.
1139 ptr32[2] = SkEndian_SwapBE32(0x0000f351); 1166 ptr32[2] = SkEndian_SwapBE32(0x0000f351);
1140 ptr32[3] = SkEndian_SwapBE32(0x00010000); 1167 ptr32[3] = SkEndian_SwapBE32(0x00010000);
1141 ptr32[4] = SkEndian_SwapBE32(0x000116cc); 1168 ptr32[4] = SkEndian_SwapBE32(0x000116cc);
1142 ptr += kTAG_XYZ_Bytes; 1169 ptr += kTAG_XYZ_Bytes;
1143 1170
1144 // Write copyright tag 1171 // Write copyright tag
1145 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag)); 1172 memcpy(ptr, gEmptyTextTag, sizeof(gEmptyTextTag));
1146 1173
1147 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if 1174 // TODO (msarett): Should we try to hold onto the data so we can return imme diately if
1148 // the client calls again? 1175 // the client calls again?
1149 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize); 1176 return SkData::MakeFromMalloc(profile.release(), kICCProfileSize);
1150 } 1177 }
OLDNEW
« no previous file with comments | « src/codec/SkPngCodec.cpp ('k') | src/core/SkColorSpaceXform.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698