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

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

Issue 2697863003: color: Clarify default behaviors (Closed)
Patch Set: Do less 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 // static
19 if (primary_id < 0 || primary_id > static_cast<int>(PrimaryID::LAST)) 19 ColorSpace ColorSpace::CreateVideo(int video_primary,
20 return PrimaryID::UNKNOWN; 20 int video_transfer,
21 if (primary_id > static_cast<int>(PrimaryID::LAST_STANDARD_VALUE) && 21 int video_matrix,
22 primary_id < 1000) 22 RangeID range_id) {
23 return PrimaryID::UNKNOWN; 23 ColorSpace result;
24 return static_cast<PrimaryID>(primary_id); 24
25 int first_primary = static_cast<int>(PrimaryID::FIRST_VIDEO_VALUE);
26 int last_primary = static_cast<int>(PrimaryID::LAST_VIDEO_VALUE);
27 if (video_primary < 0 || video_primary > last_primary - first_primary) {
28 result.primaries_ = PrimaryID::BT709;
29 } else {
30 result.primaries_ = static_cast<PrimaryID>(video_primary + first_primary);
31 }
32
33 int first_transfer = static_cast<int>(TransferID::FIRST_VIDEO_VALUE);
34 int last_transfer = static_cast<int>(TransferID::LAST_VIDEO_VALUE);
35 if (video_transfer < 0 || video_transfer > last_transfer - first_transfer) {
36 result.transfer_ = TransferID::BT709;
37 } else {
38 result.transfer_ = static_cast<TransferID>(video_transfer + first_transfer);
39 }
40
41 int first_matrix = static_cast<int>(MatrixID::FIRST_VIDEO_VALUE);
42 int last_matrix = static_cast<int>(MatrixID::LAST_VIDEO_VALUE);
43 if (video_matrix < 0 || video_matrix > last_matrix - first_matrix) {
44 result.matrix_ = MatrixID::BT709;
45 } else {
46 result.matrix_ = static_cast<MatrixID>(video_matrix + first_matrix);
47 }
48
49 result.range_ = range_id;
50 return result;
25 } 51 }
26 52
27 ColorSpace::TransferID ColorSpace::TransferIDFromInt(int transfer_id) { 53 void ColorSpace::GetVideoParameters(int* video_primary,
28 if (transfer_id < 0 || transfer_id > static_cast<int>(TransferID::LAST)) 54 int* video_transfer,
29 return TransferID::UNKNOWN; 55 int* video_matrix,
30 if (transfer_id > static_cast<int>(TransferID::LAST_STANDARD_VALUE) && 56 bool* full_range) {
31 transfer_id < 1000) 57 int first_primary = static_cast<int>(PrimaryID::FIRST_VIDEO_VALUE);
32 return TransferID::UNKNOWN; 58 int last_primary = static_cast<int>(PrimaryID::LAST_VIDEO_VALUE);
33 return static_cast<TransferID>(transfer_id); 59 *video_primary = static_cast<int>(primaries_) - first_primary;
34 } 60 if (*video_primary < 0 || *video_primary > last_primary - first_primary) {
61 *video_primary = static_cast<int>(PrimaryID::BT709) - first_primary;
62 }
35 63
36 ColorSpace::MatrixID ColorSpace::MatrixIDFromInt(int matrix_id) { 64 int first_transfer = static_cast<int>(TransferID::FIRST_VIDEO_VALUE);
37 if (matrix_id < 0 || matrix_id > static_cast<int>(MatrixID::LAST)) 65 int last_transfer = static_cast<int>(TransferID::LAST_VIDEO_VALUE);
38 return MatrixID::UNKNOWN; 66 *video_transfer = static_cast<int>(transfer_) - first_transfer;
39 if (matrix_id > static_cast<int>(MatrixID::LAST_STANDARD_VALUE) && 67 if (*video_transfer < 0 || *video_transfer > last_transfer - first_transfer) {
40 matrix_id < 1000) 68 *video_transfer = static_cast<int>(TransferID::BT709) - first_transfer;
41 return MatrixID::UNKNOWN; 69 }
42 return static_cast<MatrixID>(matrix_id); 70
71 int first_matrix = static_cast<int>(MatrixID::FIRST_VIDEO_VALUE);
72 int last_matrix = static_cast<int>(MatrixID::LAST_VIDEO_VALUE);
73 *video_matrix = static_cast<int>(matrix_) - first_matrix;
74 if (*video_matrix < 0 || *video_matrix > last_matrix - first_matrix) {
75 *video_matrix = static_cast<int>(MatrixID::BT709) - first_matrix;
76 }
77
78 switch (range_) {
79 case RangeID::FULL:
80 *full_range = true;
81 break;
82 case RangeID::UNSPECIFIED:
83 case RangeID::LIMITED:
84 case RangeID::DERIVED:
85 case RangeID::INVALID:
86 *full_range = false;
87 break;
88 }
43 } 89 }
44 90
45 ColorSpace::ColorSpace() {} 91 ColorSpace::ColorSpace() {}
46 92
47 ColorSpace::ColorSpace(PrimaryID primaries, 93 ColorSpace::ColorSpace(PrimaryID primaries,
48 TransferID transfer) 94 TransferID transfer)
49 : primaries_(primaries), 95 : primaries_(primaries),
50 transfer_(transfer), 96 transfer_(transfer),
51 matrix_(MatrixID::RGB), 97 matrix_(MatrixID::RGB),
52 range_(RangeID::FULL) {} 98 range_(RangeID::FULL) {}
53 99
54 ColorSpace::ColorSpace(PrimaryID primaries, 100 ColorSpace::ColorSpace(PrimaryID primaries,
55 TransferID transfer, 101 TransferID transfer,
56 MatrixID matrix, 102 MatrixID matrix,
57 RangeID range) 103 RangeID range)
58 : primaries_(primaries), 104 : primaries_(primaries),
59 transfer_(transfer), 105 transfer_(transfer),
60 matrix_(matrix), 106 matrix_(matrix),
61 range_(range) {} 107 range_(range) {}
62 108
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) 109 ColorSpace::ColorSpace(const ColorSpace& other)
70 : primaries_(other.primaries_), 110 : primaries_(other.primaries_),
71 transfer_(other.transfer_), 111 transfer_(other.transfer_),
72 matrix_(other.matrix_), 112 matrix_(other.matrix_),
73 range_(other.range_), 113 range_(other.range_),
74 icc_profile_id_(other.icc_profile_id_), 114 icc_profile_id_(other.icc_profile_id_),
75 icc_profile_sk_color_space_(other.icc_profile_sk_color_space_) { 115 icc_profile_sk_color_space_(other.icc_profile_sk_color_space_) {
76 if (transfer_ == TransferID::CUSTOM) { 116 if (transfer_ == TransferID::CUSTOM) {
77 memcpy(custom_transfer_params_, other.custom_transfer_params_, 117 memcpy(custom_transfer_params_, other.custom_transfer_params_,
78 sizeof(custom_transfer_params_)); 118 sizeof(custom_transfer_params_));
79 } 119 }
80 if (primaries_ == PrimaryID::CUSTOM) { 120 if (primaries_ == PrimaryID::CUSTOM) {
81 memcpy(custom_primary_matrix_, other.custom_primary_matrix_, 121 memcpy(custom_primary_matrix_, other.custom_primary_matrix_,
82 sizeof(custom_primary_matrix_)); 122 sizeof(custom_primary_matrix_));
83 } 123 }
84 } 124 }
85
86 ColorSpace::~ColorSpace() = default; 125 ColorSpace::~ColorSpace() = default;
87 126
88 bool ColorSpace::IsValid() const { 127 bool ColorSpace::IsValid() const {
89 return *this != gfx::ColorSpace(); 128 return primaries_ != PrimaryID::INVALID && transfer_ != TransferID::INVALID &&
129 matrix_ != MatrixID::INVALID && range_ != RangeID::INVALID;
90 } 130 }
91 131
92 // static 132 // static
93 ColorSpace ColorSpace::CreateSRGB() { 133 ColorSpace ColorSpace::CreateSRGB() {
94 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB, 134 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
95 RangeID::FULL); 135 RangeID::FULL);
96 } 136 }
97 137
98 // static 138 // static
99 ColorSpace ColorSpace::CreateSCRGBLinear() { 139 ColorSpace ColorSpace::CreateSCRGBLinear() {
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 return false; 230 return false;
191 } 231 }
192 232
193 sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const { 233 sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const {
194 // If we got a specific SkColorSpace from the ICCProfile that this color space 234 // If we got a specific SkColorSpace from the ICCProfile that this color space
195 // was created from, use that. 235 // was created from, use that.
196 if (icc_profile_sk_color_space_) 236 if (icc_profile_sk_color_space_)
197 return icc_profile_sk_color_space_; 237 return icc_profile_sk_color_space_;
198 238
199 // Unspecified color spaces correspond to the null SkColorSpace. 239 // Unspecified color spaces correspond to the null SkColorSpace.
200 if (primaries_ == PrimaryID::UNSPECIFIED || 240 if (!IsValid())
201 transfer_ == TransferID::UNSPECIFIED) {
202 return nullptr; 241 return nullptr;
203 }
204 242
205 // Handle only full-range RGB spaces. 243 // Handle only full-range RGB spaces.
206 if (matrix_ != MatrixID::RGB) { 244 if (matrix_ != MatrixID::RGB) {
207 DLOG(ERROR) << "Not creating non-RGB SkColorSpace"; 245 DLOG(ERROR) << "Not creating non-RGB SkColorSpace";
208 return nullptr; 246 return nullptr;
209 } 247 }
210 if (range_ != RangeID::FULL) { 248 if (range_ != RangeID::FULL) {
211 DLOG(ERROR) << "Not creating non-full-range SkColorSpace"; 249 DLOG(ERROR) << "Not creating non-full-range SkColorSpace";
212 return nullptr; 250 return nullptr;
213 } 251 }
(...skipping 28 matching lines...) Expand all
242 return SkColorSpace::MakeRGB(fn, to_xyz_d50); 280 return SkColorSpace::MakeRGB(fn, to_xyz_d50);
243 } 281 }
244 282
245 void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const { 283 void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const {
246 SkColorSpacePrimaries primaries = {0}; 284 SkColorSpacePrimaries primaries = {0};
247 switch (primaries_) { 285 switch (primaries_) {
248 case ColorSpace::PrimaryID::CUSTOM: 286 case ColorSpace::PrimaryID::CUSTOM:
249 to_XYZD50->set3x3RowMajorf(custom_primary_matrix_); 287 to_XYZD50->set3x3RowMajorf(custom_primary_matrix_);
250 return; 288 return;
251 289
290 case ColorSpace::PrimaryID::INVALID:
291 to_XYZD50->setIdentity();
292 return;
293
252 case ColorSpace::PrimaryID::RESERVED0: 294 case ColorSpace::PrimaryID::RESERVED0:
253 case ColorSpace::PrimaryID::RESERVED: 295 case ColorSpace::PrimaryID::RESERVED:
254 case ColorSpace::PrimaryID::UNSPECIFIED: 296 case ColorSpace::PrimaryID::UNSPECIFIED:
255 case ColorSpace::PrimaryID::UNKNOWN:
256 case ColorSpace::PrimaryID::BT709: 297 case ColorSpace::PrimaryID::BT709:
257 // BT709 is our default case. Put it after the switch just 298 // 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. 299 // 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 300 // (We don't want to use "default", because we want the compiler
260 // to tell us if we forgot some enum values.) 301 // to tell us if we forgot some enum values.)
261 primaries.fRX = 0.640f; 302 primaries.fRX = 0.640f;
262 primaries.fRY = 0.330f; 303 primaries.fRY = 0.330f;
263 primaries.fGX = 0.300f; 304 primaries.fGX = 0.300f;
264 primaries.fGY = 0.600f; 305 primaries.fGY = 0.600f;
265 primaries.fBX = 0.150f; 306 primaries.fBX = 0.150f;
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 return true; 451 return true;
411 case ColorSpace::TransferID::GAMMA24: 452 case ColorSpace::TransferID::GAMMA24:
412 fn->fG = 2.4f; 453 fn->fG = 2.4f;
413 return true; 454 return true;
414 case ColorSpace::TransferID::GAMMA28: 455 case ColorSpace::TransferID::GAMMA28:
415 fn->fG = 2.8f; 456 fn->fG = 2.8f;
416 return true; 457 return true;
417 case ColorSpace::TransferID::RESERVED0: 458 case ColorSpace::TransferID::RESERVED0:
418 case ColorSpace::TransferID::RESERVED: 459 case ColorSpace::TransferID::RESERVED:
419 case ColorSpace::TransferID::UNSPECIFIED: 460 case ColorSpace::TransferID::UNSPECIFIED:
420 case ColorSpace::TransferID::UNKNOWN:
421 // All unknown values default to BT709
422 case ColorSpace::TransferID::BT709: 461 case ColorSpace::TransferID::BT709:
423 case ColorSpace::TransferID::SMPTE170M: 462 case ColorSpace::TransferID::SMPTE170M:
424 case ColorSpace::TransferID::BT2020_10: 463 case ColorSpace::TransferID::BT2020_10:
425 case ColorSpace::TransferID::BT2020_12: 464 case ColorSpace::TransferID::BT2020_12:
426 fn->fA = 0.909672431050f; 465 fn->fA = 0.909672431050f;
427 fn->fB = 0.090327568950f; 466 fn->fB = 0.090327568950f;
428 fn->fC = 0.222222222222f; 467 fn->fC = 0.222222222222f;
429 fn->fD = 0.081242862158f; 468 fn->fD = 0.081242862158f;
430 fn->fG = 2.222222222222f; 469 fn->fG = 2.222222222222f;
431 return true; 470 return true;
(...skipping 19 matching lines...) Expand all
451 case ColorSpace::TransferID::IEC61966_2_4: 490 case ColorSpace::TransferID::IEC61966_2_4:
452 // This could potentially be represented the same as IEC61966_2_1, but 491 // This could potentially be represented the same as IEC61966_2_1, but
453 // it handles negative values differently. 492 // it handles negative values differently.
454 break; 493 break;
455 case ColorSpace::TransferID::ARIB_STD_B67: 494 case ColorSpace::TransferID::ARIB_STD_B67:
456 case ColorSpace::TransferID::BT1361_ECG: 495 case ColorSpace::TransferID::BT1361_ECG:
457 case ColorSpace::TransferID::LOG: 496 case ColorSpace::TransferID::LOG:
458 case ColorSpace::TransferID::LOG_SQRT: 497 case ColorSpace::TransferID::LOG_SQRT:
459 case ColorSpace::TransferID::SMPTEST2084: 498 case ColorSpace::TransferID::SMPTEST2084:
460 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: 499 case ColorSpace::TransferID::SMPTEST2084_NON_HDR:
500 case ColorSpace::TransferID::INVALID:
461 break; 501 break;
462 } 502 }
463 503
464 return false; 504 return false;
465 } 505 }
466 506
467 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const { 507 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const {
468 if (!GetTransferFunction(fn)) 508 if (!GetTransferFunction(fn))
469 return false; 509 return false;
470 *fn = SkTransferFnInverse(*fn); 510 *fn = SkTransferFnInverse(*fn);
471 return true; 511 return true;
472 } 512 }
473 513
474 void ColorSpace::GetTransferMatrix(SkMatrix44* matrix) const { 514 void ColorSpace::GetTransferMatrix(SkMatrix44* matrix) const {
475 float Kr = 0; 515 float Kr = 0;
476 float Kb = 0; 516 float Kb = 0;
477 switch (matrix_) { 517 switch (matrix_) {
478 case ColorSpace::MatrixID::RGB: 518 case ColorSpace::MatrixID::RGB:
519 case ColorSpace::MatrixID::INVALID:
479 matrix->setIdentity(); 520 matrix->setIdentity();
480 return; 521 return;
481 522
482 case ColorSpace::MatrixID::BT709: 523 case ColorSpace::MatrixID::BT709:
483 case ColorSpace::MatrixID::UNSPECIFIED: 524 case ColorSpace::MatrixID::UNSPECIFIED:
484 case ColorSpace::MatrixID::RESERVED: 525 case ColorSpace::MatrixID::RESERVED:
485 case ColorSpace::MatrixID::UNKNOWN:
486 Kr = 0.2126f; 526 Kr = 0.2126f;
487 Kb = 0.0722f; 527 Kb = 0.0722f;
488 break; 528 break;
489 529
490 case ColorSpace::MatrixID::FCC: 530 case ColorSpace::MatrixID::FCC:
491 Kr = 0.30f; 531 Kr = 0.30f;
492 Kb = 0.11f; 532 Kb = 0.11f;
493 break; 533 break;
494 534
495 case ColorSpace::MatrixID::BT470BG: 535 case ColorSpace::MatrixID::BT470BG:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 v_m * (1.0f - Kr), v_m * -Kg, v_m * -Kb, 0.5f, // V 596 v_m * (1.0f - Kr), v_m * -Kg, v_m * -Kb, 0.5f, // V
557 0.0f, 0.0f, 0.0f, 1.0f, 597 0.0f, 0.0f, 0.0f, 1.0f,
558 }; 598 };
559 matrix->setRowMajorf(data); 599 matrix->setRowMajorf(data);
560 } 600 }
561 601
562 void ColorSpace::GetRangeAdjustMatrix(SkMatrix44* matrix) const { 602 void ColorSpace::GetRangeAdjustMatrix(SkMatrix44* matrix) const {
563 switch (range_) { 603 switch (range_) {
564 case RangeID::FULL: 604 case RangeID::FULL:
565 case RangeID::UNSPECIFIED: 605 case RangeID::UNSPECIFIED:
606 case RangeID::INVALID:
566 matrix->setIdentity(); 607 matrix->setIdentity();
567 return; 608 return;
568 609
569 case RangeID::DERIVED: 610 case RangeID::DERIVED:
570 case RangeID::LIMITED: 611 case RangeID::LIMITED:
571 break; 612 break;
572 } 613 }
573 switch (matrix_) { 614 switch (matrix_) {
574 case MatrixID::RGB: 615 case MatrixID::RGB:
616 case MatrixID::INVALID:
575 case MatrixID::YCOCG: 617 case MatrixID::YCOCG:
576 matrix->setScale(255.0f/219.0f, 255.0f/219.0f, 255.0f/219.0f); 618 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); 619 matrix->postTranslate(-16.0f/219.0f, -16.0f/219.0f, -16.0f/219.0f);
578 break; 620 break;
579 621
580 case MatrixID::BT709: 622 case MatrixID::BT709:
581 case MatrixID::UNSPECIFIED: 623 case MatrixID::UNSPECIFIED:
582 case MatrixID::RESERVED: 624 case MatrixID::RESERVED:
583 case MatrixID::FCC: 625 case MatrixID::FCC:
584 case MatrixID::BT470BG: 626 case MatrixID::BT470BG:
585 case MatrixID::SMPTE170M: 627 case MatrixID::SMPTE170M:
586 case MatrixID::SMPTE240M: 628 case MatrixID::SMPTE240M:
587 case MatrixID::BT2020_NCL: 629 case MatrixID::BT2020_NCL:
588 case MatrixID::BT2020_CL: 630 case MatrixID::BT2020_CL:
589 case MatrixID::YDZDX: 631 case MatrixID::YDZDX:
590 case MatrixID::UNKNOWN:
591 matrix->setScale(255.0f/219.0f, 255.0f/224.0f, 255.0f/224.0f); 632 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); 633 matrix->postTranslate(-16.0f/219.0f, -15.5f/224.0f, -15.5f/224.0f);
593 break; 634 break;
594 } 635 }
595 } 636 }
596 637
597 } // namespace gfx 638 } // namespace gfx
OLDNEW
« ui/gfx/color_space.h ('K') | « ui/gfx/color_space.h ('k') | ui/gfx/color_space_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698