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

Side by Side Diff: ui/gfx/color_space.cc

Issue 2697863003: color: Clarify default behaviors (Closed)
Patch Set: color: Remove redundant PrimaryID/TransferID/MatrixID values Created 3 years, 10 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/color_space.h" 5 #include "ui/gfx/color_space.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/synchronization/lock.h" 10 #include "base/synchronization/lock.h"
11 #include "third_party/skia/include/core/SkColorSpace.h" 11 #include "third_party/skia/include/core/SkColorSpace.h"
12 #include "ui/gfx/icc_profile.h" 12 #include "ui/gfx/icc_profile.h"
13 #include "ui/gfx/skia_color_space_util.h" 13 #include "ui/gfx/skia_color_space_util.h"
14 #include "ui/gfx/transform.h" 14 #include "ui/gfx/transform.h"
15 15
16 namespace gfx { 16 namespace gfx {
17 17
18 ColorSpace::PrimaryID ColorSpace::PrimaryIDFromInt(int primary_id) { 18 ColorSpace::PrimaryID ColorSpace::PrimaryIDFromH264(int primary_id) {
19 if (primary_id < 0 || primary_id > static_cast<int>(PrimaryID::LAST)) 19 // These values should match the H264 specification (see Table E-3
20 return PrimaryID::UNKNOWN; 20 // Colour Primaries in https://www.itu.int/rec/T-REC-H.264/en).
21 if (primary_id > static_cast<int>(PrimaryID::LAST_STANDARD_VALUE) && 21 switch (primary_id) {
22 primary_id < 1000) 22 case 0: // RESERVED0
23 return PrimaryID::UNKNOWN; 23 break;
24 return static_cast<PrimaryID>(primary_id); 24 case 1:
25 return PrimaryID::BT709;
26 case 2: // UNSPECIFIED
27 break;
28 case 3: // RESERVED
29 break;
30 case 4:
31 return PrimaryID::BT470M;
32 case 5:
33 return PrimaryID::BT470BG;
34 case 6:
35 return PrimaryID::SMPTE170M;
36 case 7:
37 return PrimaryID::SMPTE240M;
38 case 8:
39 return PrimaryID::FILM;
40 case 9:
41 return PrimaryID::BT2020;
42 case 10:
43 return PrimaryID::SMPTEST428_1;
44 case 11:
45 return PrimaryID::SMPTEST431_2;
46 case 12:
47 return PrimaryID::SMPTEST432_1;
48 default:
49 break;
50 }
51 // All unknown values default to BT709.
hubbe 2017/02/15 23:30:43 This limits our ability to make smart guesses base
52 return PrimaryID::BT709;
25 } 53 }
26 54
27 ColorSpace::TransferID ColorSpace::TransferIDFromInt(int transfer_id) { 55 ColorSpace::TransferID ColorSpace::TransferIDFromH264(int transfer_id) {
28 if (transfer_id < 0 || transfer_id > static_cast<int>(TransferID::LAST)) 56 switch (transfer_id) {
29 return TransferID::UNKNOWN; 57 case 0: // RESERVED0
30 if (transfer_id > static_cast<int>(TransferID::LAST_STANDARD_VALUE) && 58 break;
31 transfer_id < 1000) 59 case 1:
32 return TransferID::UNKNOWN; 60 return TransferID::BT709;
33 return static_cast<TransferID>(transfer_id); 61 case 2: // UNSPECIFIED
62 break;
63 case 3: // RESERVED
64 break;
65 case 4:
66 return TransferID::GAMMA22;
67 case 5:
68 return TransferID::GAMMA28;
69 case 6:
70 return TransferID::SMPTE170M;
71 case 7:
72 return TransferID::SMPTE240M;
73 case 8:
74 return TransferID::LINEAR;
75 case 9:
76 return TransferID::LOG;
77 case 10:
78 return TransferID::LOG_SQRT;
79 case 11:
80 return TransferID::IEC61966_2_4;
81 case 12:
82 return TransferID::BT1361_ECG;
83 case 13:
84 return TransferID::IEC61966_2_1;
85 case 14:
86 return TransferID::BT2020_10;
87 case 15:
88 return TransferID::BT2020_12;
89 case 16:
90 return TransferID::SMPTEST2084;
91 case 17:
92 return TransferID::SMPTEST428_1;
93 case 18:
94 return TransferID::ARIB_STD_B67;
95 default:
96 break;
97 }
98 // All unknown values default to BT709
99 return TransferID::BT709;
34 } 100 }
35 101
36 ColorSpace::MatrixID ColorSpace::MatrixIDFromInt(int matrix_id) { 102 ColorSpace::MatrixID ColorSpace::MatrixIDFromH264(int matrix_id) {
37 if (matrix_id < 0 || matrix_id > static_cast<int>(MatrixID::LAST)) 103 // The first 0-255 values should match the H264 specification (see Table E-5
38 return MatrixID::UNKNOWN; 104 // Matrix Coefficients in https://www.itu.int/rec/T-REC-H.264/en).
39 if (matrix_id > static_cast<int>(MatrixID::LAST_STANDARD_VALUE) && 105 switch (matrix_id) {
40 matrix_id < 1000) 106 case 0:
41 return MatrixID::UNKNOWN; 107 return MatrixID::RGB;
42 return static_cast<MatrixID>(matrix_id); 108 case 1:
109 return MatrixID::BT709;
110 case 2: // UNSPECIFIED
111 break;
112 case 3: // RESERVED
113 break;
114 case 4:
115 return MatrixID::FCC;
116 case 5:
117 return MatrixID::BT470BG;
118 case 6:
119 return MatrixID::SMPTE170M;
120 case 7:
121 return MatrixID::SMPTE240M;
122 case 8:
123 return MatrixID::YCOCG;
124 case 9:
125 return MatrixID::BT2020_NCL;
126 case 10:
127 return MatrixID::BT2020_CL;
128 case 11:
129 return MatrixID::YDZDX;
130 default:
131 break;
132 }
133 // All unknown values default to BT709
134 return MatrixID::BT709;
43 } 135 }
44 136
45 ColorSpace::ColorSpace() {} 137 ColorSpace::ColorSpace() {}
46 138
47 ColorSpace::ColorSpace(PrimaryID primaries, 139 ColorSpace::ColorSpace(PrimaryID primaries,
48 TransferID transfer) 140 TransferID transfer)
49 : primaries_(primaries), 141 : primaries_(primaries),
50 transfer_(transfer), 142 transfer_(transfer),
51 matrix_(MatrixID::RGB), 143 matrix_(MatrixID::RGB),
52 range_(RangeID::FULL) {} 144 range_(RangeID::FULL) {}
53 145
54 ColorSpace::ColorSpace(PrimaryID primaries, 146 ColorSpace::ColorSpace(PrimaryID primaries,
55 TransferID transfer, 147 TransferID transfer,
56 MatrixID matrix, 148 MatrixID matrix,
57 RangeID range) 149 RangeID range)
58 : primaries_(primaries), 150 : primaries_(primaries),
59 transfer_(transfer), 151 transfer_(transfer),
60 matrix_(matrix), 152 matrix_(matrix),
61 range_(range) {} 153 range_(range) {}
62 154
63 ColorSpace::ColorSpace(int primaries, int transfer, int matrix, RangeID range)
64 : primaries_(PrimaryIDFromInt(primaries)),
65 transfer_(TransferIDFromInt(transfer)),
66 matrix_(MatrixIDFromInt(matrix)),
67 range_(range) {}
68
69 ColorSpace::ColorSpace(const ColorSpace& other) 155 ColorSpace::ColorSpace(const ColorSpace& other)
70 : primaries_(other.primaries_), 156 : primaries_(other.primaries_),
71 transfer_(other.transfer_), 157 transfer_(other.transfer_),
72 matrix_(other.matrix_), 158 matrix_(other.matrix_),
73 range_(other.range_), 159 range_(other.range_),
74 icc_profile_id_(other.icc_profile_id_), 160 icc_profile_id_(other.icc_profile_id_),
75 icc_profile_sk_color_space_(other.icc_profile_sk_color_space_) { 161 icc_profile_sk_color_space_(other.icc_profile_sk_color_space_) {
76 if (transfer_ == TransferID::CUSTOM) { 162 if (transfer_ == TransferID::CUSTOM) {
77 memcpy(custom_transfer_params_, other.custom_transfer_params_, 163 memcpy(custom_transfer_params_, other.custom_transfer_params_,
78 sizeof(custom_transfer_params_)); 164 sizeof(custom_transfer_params_));
79 } 165 }
80 if (primaries_ == PrimaryID::CUSTOM) { 166 if (primaries_ == PrimaryID::CUSTOM) {
81 memcpy(custom_primary_matrix_, other.custom_primary_matrix_, 167 memcpy(custom_primary_matrix_, other.custom_primary_matrix_,
82 sizeof(custom_primary_matrix_)); 168 sizeof(custom_primary_matrix_));
83 } 169 }
84 } 170 }
85 171
86 ColorSpace::~ColorSpace() = default; 172 ColorSpace::~ColorSpace() = default;
87 173
88 bool ColorSpace::IsValid() const { 174 bool ColorSpace::IsValid() const {
89 return *this != gfx::ColorSpace(); 175 return primaries_ != PrimaryID::INVALID && transfer_ != TransferID::INVALID;
90 } 176 }
91 177
92 // static 178 // static
93 ColorSpace ColorSpace::CreateSRGB() { 179 ColorSpace ColorSpace::CreateSRGB() {
94 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB, 180 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
95 RangeID::FULL); 181 RangeID::FULL);
96 } 182 }
97 183
98 // static 184 // static
99 ColorSpace ColorSpace::CreateSCRGBLinear() { 185 ColorSpace ColorSpace::CreateSCRGBLinear() {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 return false; 276 return false;
191 } 277 }
192 278
193 sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const { 279 sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const {
194 // If we got a specific SkColorSpace from the ICCProfile that this color space 280 // If we got a specific SkColorSpace from the ICCProfile that this color space
195 // was created from, use that. 281 // was created from, use that.
196 if (icc_profile_sk_color_space_) 282 if (icc_profile_sk_color_space_)
197 return icc_profile_sk_color_space_; 283 return icc_profile_sk_color_space_;
198 284
199 // Unspecified color spaces correspond to the null SkColorSpace. 285 // Unspecified color spaces correspond to the null SkColorSpace.
200 if (primaries_ == PrimaryID::UNSPECIFIED || 286 if (!IsValid())
201 transfer_ == TransferID::UNSPECIFIED) {
202 return nullptr; 287 return nullptr;
203 }
204 288
205 // Handle only full-range RGB spaces. 289 // Handle only full-range RGB spaces.
206 if (matrix_ != MatrixID::RGB) { 290 if (matrix_ != MatrixID::RGB) {
207 DLOG(ERROR) << "Not creating non-RGB SkColorSpace"; 291 DLOG(ERROR) << "Not creating non-RGB SkColorSpace";
208 return nullptr; 292 return nullptr;
209 } 293 }
210 if (range_ != RangeID::FULL) { 294 if (range_ != RangeID::FULL) {
211 DLOG(ERROR) << "Not creating non-full-range SkColorSpace"; 295 DLOG(ERROR) << "Not creating non-full-range SkColorSpace";
212 return nullptr; 296 return nullptr;
213 } 297 }
(...skipping 28 matching lines...) Expand all
242 return SkColorSpace::MakeRGB(fn, to_xyz_d50); 326 return SkColorSpace::MakeRGB(fn, to_xyz_d50);
243 } 327 }
244 328
245 void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const { 329 void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const {
246 SkColorSpacePrimaries primaries = {0}; 330 SkColorSpacePrimaries primaries = {0};
247 switch (primaries_) { 331 switch (primaries_) {
248 case ColorSpace::PrimaryID::CUSTOM: 332 case ColorSpace::PrimaryID::CUSTOM:
249 to_XYZD50->set3x3RowMajorf(custom_primary_matrix_); 333 to_XYZD50->set3x3RowMajorf(custom_primary_matrix_);
250 return; 334 return;
251 335
252 case ColorSpace::PrimaryID::RESERVED0: 336 case ColorSpace::PrimaryID::INVALID:
253 case ColorSpace::PrimaryID::RESERVED: 337 to_XYZD50->setIdentity();
254 case ColorSpace::PrimaryID::UNSPECIFIED: 338 return;
255 case ColorSpace::PrimaryID::UNKNOWN: 339
256 case ColorSpace::PrimaryID::BT709: 340 case ColorSpace::PrimaryID::BT709:
257 // BT709 is our default case. Put it after the switch just 341 // BT709 is our default case. Put it after the switch just
258 // in case we somehow get an id which is not listed in the switch. 342 // in case we somehow get an id which is not listed in the switch.
259 // (We don't want to use "default", because we want the compiler 343 // (We don't want to use "default", because we want the compiler
260 // to tell us if we forgot some enum values.) 344 // to tell us if we forgot some enum values.)
261 primaries.fRX = 0.640f; 345 primaries.fRX = 0.640f;
262 primaries.fRY = 0.330f; 346 primaries.fRY = 0.330f;
263 primaries.fGX = 0.300f; 347 primaries.fGX = 0.300f;
264 primaries.fGY = 0.600f; 348 primaries.fGY = 0.600f;
265 primaries.fBX = 0.150f; 349 primaries.fBX = 0.150f;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
407 return true; 491 return true;
408 case ColorSpace::TransferID::GAMMA22: 492 case ColorSpace::TransferID::GAMMA22:
409 fn->fG = 2.2f; 493 fn->fG = 2.2f;
410 return true; 494 return true;
411 case ColorSpace::TransferID::GAMMA24: 495 case ColorSpace::TransferID::GAMMA24:
412 fn->fG = 2.4f; 496 fn->fG = 2.4f;
413 return true; 497 return true;
414 case ColorSpace::TransferID::GAMMA28: 498 case ColorSpace::TransferID::GAMMA28:
415 fn->fG = 2.8f; 499 fn->fG = 2.8f;
416 return true; 500 return true;
417 case ColorSpace::TransferID::RESERVED0:
418 case ColorSpace::TransferID::RESERVED:
419 case ColorSpace::TransferID::UNSPECIFIED:
420 case ColorSpace::TransferID::UNKNOWN:
421 // All unknown values default to BT709
422 case ColorSpace::TransferID::BT709: 501 case ColorSpace::TransferID::BT709:
423 case ColorSpace::TransferID::SMPTE170M: 502 case ColorSpace::TransferID::SMPTE170M:
424 case ColorSpace::TransferID::BT2020_10: 503 case ColorSpace::TransferID::BT2020_10:
425 case ColorSpace::TransferID::BT2020_12: 504 case ColorSpace::TransferID::BT2020_12:
426 fn->fA = 0.909672431050f; 505 fn->fA = 0.909672431050f;
427 fn->fB = 0.090327568950f; 506 fn->fB = 0.090327568950f;
428 fn->fC = 0.222222222222f; 507 fn->fC = 0.222222222222f;
429 fn->fD = 0.081242862158f; 508 fn->fD = 0.081242862158f;
430 fn->fG = 2.222222222222f; 509 fn->fG = 2.222222222222f;
431 return true; 510 return true;
(...skipping 19 matching lines...) Expand all
451 case ColorSpace::TransferID::IEC61966_2_4: 530 case ColorSpace::TransferID::IEC61966_2_4:
452 // This could potentially be represented the same as IEC61966_2_1, but 531 // This could potentially be represented the same as IEC61966_2_1, but
453 // it handles negative values differently. 532 // it handles negative values differently.
454 break; 533 break;
455 case ColorSpace::TransferID::ARIB_STD_B67: 534 case ColorSpace::TransferID::ARIB_STD_B67:
456 case ColorSpace::TransferID::BT1361_ECG: 535 case ColorSpace::TransferID::BT1361_ECG:
457 case ColorSpace::TransferID::LOG: 536 case ColorSpace::TransferID::LOG:
458 case ColorSpace::TransferID::LOG_SQRT: 537 case ColorSpace::TransferID::LOG_SQRT:
459 case ColorSpace::TransferID::SMPTEST2084: 538 case ColorSpace::TransferID::SMPTEST2084:
460 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: 539 case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
540 case ColorSpace::TransferID::INVALID:
461 break; 541 break;
462 } 542 }
463 543
464 return false; 544 return false;
465 } 545 }
466 546
467 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const { 547 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const {
468 if (!GetTransferFunction(fn)) 548 if (!GetTransferFunction(fn))
469 return false; 549 return false;
470 *fn = SkTransferFnInverse(*fn); 550 *fn = SkTransferFnInverse(*fn);
471 return true; 551 return true;
472 } 552 }
473 553
474 void ColorSpace::GetTransferMatrix(SkMatrix44* matrix) const { 554 void ColorSpace::GetTransferMatrix(SkMatrix44* matrix) const {
475 float Kr = 0; 555 float Kr = 0;
476 float Kb = 0; 556 float Kb = 0;
477 switch (matrix_) { 557 switch (matrix_) {
478 case ColorSpace::MatrixID::RGB: 558 case ColorSpace::MatrixID::RGB:
479 matrix->setIdentity(); 559 matrix->setIdentity();
480 return; 560 return;
481 561
482 case ColorSpace::MatrixID::BT709: 562 case ColorSpace::MatrixID::BT709:
483 case ColorSpace::MatrixID::UNSPECIFIED:
484 case ColorSpace::MatrixID::RESERVED:
485 case ColorSpace::MatrixID::UNKNOWN:
486 Kr = 0.2126f; 563 Kr = 0.2126f;
487 Kb = 0.0722f; 564 Kb = 0.0722f;
488 break; 565 break;
489 566
490 case ColorSpace::MatrixID::FCC: 567 case ColorSpace::MatrixID::FCC:
491 Kr = 0.30f; 568 Kr = 0.30f;
492 Kb = 0.11f; 569 Kb = 0.11f;
493 break; 570 break;
494 571
495 case ColorSpace::MatrixID::BT470BG: 572 case ColorSpace::MatrixID::BT470BG:
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 u_m * -Kr, u_m * -Kg, u_m * (1.0f - Kb), 0.5f, // U 632 u_m * -Kr, u_m * -Kg, u_m * (1.0f - Kb), 0.5f, // U
556 v_m * (1.0f - Kr), v_m * -Kg, v_m * -Kb, 0.5f, // V 633 v_m * (1.0f - Kr), v_m * -Kg, v_m * -Kb, 0.5f, // V
557 0.0f, 0.0f, 0.0f, 1.0f, 634 0.0f, 0.0f, 0.0f, 1.0f,
558 }; 635 };
559 matrix->setRowMajorf(data); 636 matrix->setRowMajorf(data);
560 } 637 }
561 638
562 void ColorSpace::GetRangeAdjustMatrix(SkMatrix44* matrix) const { 639 void ColorSpace::GetRangeAdjustMatrix(SkMatrix44* matrix) const {
563 switch (range_) { 640 switch (range_) {
564 case RangeID::FULL: 641 case RangeID::FULL:
565 case RangeID::UNSPECIFIED:
566 matrix->setIdentity(); 642 matrix->setIdentity();
567 return; 643 return;
568 644
569 case RangeID::DERIVED: 645 case RangeID::DERIVED:
570 case RangeID::LIMITED: 646 case RangeID::LIMITED:
571 break; 647 break;
572 } 648 }
573 switch (matrix_) { 649 switch (matrix_) {
574 case MatrixID::RGB: 650 case MatrixID::RGB:
575 case MatrixID::YCOCG: 651 case MatrixID::YCOCG:
576 matrix->setScale(255.0f/219.0f, 255.0f/219.0f, 255.0f/219.0f); 652 matrix->setScale(255.0f/219.0f, 255.0f/219.0f, 255.0f/219.0f);
577 matrix->postTranslate(-16.0f/219.0f, -16.0f/219.0f, -16.0f/219.0f); 653 matrix->postTranslate(-16.0f/219.0f, -16.0f/219.0f, -16.0f/219.0f);
578 break; 654 break;
579 655
580 case MatrixID::BT709: 656 case MatrixID::BT709:
581 case MatrixID::UNSPECIFIED:
582 case MatrixID::RESERVED:
583 case MatrixID::FCC: 657 case MatrixID::FCC:
584 case MatrixID::BT470BG: 658 case MatrixID::BT470BG:
585 case MatrixID::SMPTE170M: 659 case MatrixID::SMPTE170M:
586 case MatrixID::SMPTE240M: 660 case MatrixID::SMPTE240M:
587 case MatrixID::BT2020_NCL: 661 case MatrixID::BT2020_NCL:
588 case MatrixID::BT2020_CL: 662 case MatrixID::BT2020_CL:
589 case MatrixID::YDZDX: 663 case MatrixID::YDZDX:
590 case MatrixID::UNKNOWN:
591 matrix->setScale(255.0f/219.0f, 255.0f/224.0f, 255.0f/224.0f); 664 matrix->setScale(255.0f/219.0f, 255.0f/224.0f, 255.0f/224.0f);
592 matrix->postTranslate(-16.0f/219.0f, -15.5f/224.0f, -15.5f/224.0f); 665 matrix->postTranslate(-16.0f/219.0f, -15.5f/224.0f, -15.5f/224.0f);
593 break; 666 break;
594 } 667 }
595 } 668 }
596 669
597 } // namespace gfx 670 } // namespace gfx
OLDNEW
« ui/gfx/color_space.h ('K') | « ui/gfx/color_space.h ('k') | ui/gfx/color_space_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698