OLD | NEW |
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/transform.h" |
13 | 14 |
14 namespace gfx { | 15 namespace gfx { |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 SkColorSpaceTransferFn InvertTransferFn(SkColorSpaceTransferFn fn) { | 19 SkColorSpaceTransferFn InvertTransferFn(SkColorSpaceTransferFn fn) { |
19 SkColorSpaceTransferFn fn_inv = {0}; | 20 SkColorSpaceTransferFn fn_inv = {0}; |
20 if (fn.fA > 0 && fn.fG > 0) { | 21 if (fn.fA > 0 && fn.fG > 0) { |
21 double a_to_the_g = pow(fn.fA, fn.fG); | 22 double a_to_the_g = pow(fn.fA, fn.fG); |
22 fn_inv.fA = 1.f / a_to_the_g; | 23 fn_inv.fA = 1.f / a_to_the_g; |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 110 } |
110 | 111 |
111 // Static | 112 // Static |
112 ColorSpace ColorSpace::CreateXYZD50() { | 113 ColorSpace ColorSpace::CreateXYZD50() { |
113 return ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR, MatrixID::RGB, | 114 return ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR, MatrixID::RGB, |
114 RangeID::FULL); | 115 RangeID::FULL); |
115 } | 116 } |
116 | 117 |
117 // static | 118 // static |
118 ColorSpace ColorSpace::CreateJpeg() { | 119 ColorSpace ColorSpace::CreateJpeg() { |
119 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::BT709, | 120 // TODO(ccameron): Determine which primaries and transfer function were |
120 RangeID::FULL); | 121 // intended here. |
| 122 return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, |
| 123 MatrixID::SMPTE170M, RangeID::FULL); |
121 } | 124 } |
122 | 125 |
123 // static | 126 // static |
124 ColorSpace ColorSpace::CreateREC601() { | 127 ColorSpace ColorSpace::CreateREC601() { |
125 return ColorSpace(PrimaryID::SMPTE170M, TransferID::SMPTE170M, | 128 return ColorSpace(PrimaryID::SMPTE170M, TransferID::SMPTE170M, |
126 MatrixID::SMPTE170M, RangeID::LIMITED); | 129 MatrixID::SMPTE170M, RangeID::LIMITED); |
127 } | 130 } |
128 | 131 |
129 // static | 132 // static |
130 ColorSpace ColorSpace::CreateREC709() { | 133 ColorSpace ColorSpace::CreateREC709() { |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 return false; | 476 return false; |
474 } | 477 } |
475 | 478 |
476 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const { | 479 bool ColorSpace::GetInverseTransferFunction(SkColorSpaceTransferFn* fn) const { |
477 if (!GetTransferFunction(fn)) | 480 if (!GetTransferFunction(fn)) |
478 return false; | 481 return false; |
479 *fn = InvertTransferFn(*fn); | 482 *fn = InvertTransferFn(*fn); |
480 return true; | 483 return true; |
481 } | 484 } |
482 | 485 |
| 486 void ColorSpace::GetTransferMatrix(SkMatrix44* matrix) const { |
| 487 float Kr = 0; |
| 488 float Kb = 0; |
| 489 switch (matrix_) { |
| 490 case ColorSpace::MatrixID::RGB: |
| 491 matrix->setIdentity(); |
| 492 return; |
| 493 |
| 494 case ColorSpace::MatrixID::BT709: |
| 495 case ColorSpace::MatrixID::UNSPECIFIED: |
| 496 case ColorSpace::MatrixID::RESERVED: |
| 497 case ColorSpace::MatrixID::UNKNOWN: |
| 498 Kr = 0.2126f; |
| 499 Kb = 0.0722f; |
| 500 break; |
| 501 |
| 502 case ColorSpace::MatrixID::FCC: |
| 503 Kr = 0.30f; |
| 504 Kb = 0.11f; |
| 505 break; |
| 506 |
| 507 case ColorSpace::MatrixID::BT470BG: |
| 508 case ColorSpace::MatrixID::SMPTE170M: |
| 509 Kr = 0.299f; |
| 510 Kb = 0.114f; |
| 511 break; |
| 512 |
| 513 case ColorSpace::MatrixID::SMPTE240M: |
| 514 Kr = 0.212f; |
| 515 Kb = 0.087f; |
| 516 break; |
| 517 |
| 518 case ColorSpace::MatrixID::YCOCG: { |
| 519 float data[16] = { |
| 520 0.25f, 0.5f, 0.25f, 0.5f, // Y |
| 521 -0.25f, 0.5f, -0.25f, 0.5f, // Cg |
| 522 0.5f, 0.0f, -0.5f, 0.0f, // Co |
| 523 0.0f, 0.0f, 0.0f, 1.0f |
| 524 }; |
| 525 matrix->setRowMajorf(data); |
| 526 return; |
| 527 } |
| 528 |
| 529 // BT2020_CL is a special case. |
| 530 // Basically we return a matrix that transforms RGB values |
| 531 // to RYB values. (We replace the green component with the |
| 532 // the luminance.) Later steps will compute the Cb & Cr values. |
| 533 case ColorSpace::MatrixID::BT2020_CL: { |
| 534 Kr = 0.2627f; |
| 535 Kb = 0.0593f; |
| 536 float data[16] = { |
| 537 1.0f, 0.0f, 0.0f, 0.0f, // R |
| 538 Kr, 1.0f - Kr - Kb, Kb, 0.0f, // Y |
| 539 0.0f, 0.0f, 1.0f, 0.0f, // B |
| 540 0.0f, 0.0f, 0.0f, 1.0f |
| 541 }; |
| 542 matrix->setRowMajorf(data); |
| 543 return; |
| 544 } |
| 545 |
| 546 case ColorSpace::MatrixID::BT2020_NCL: |
| 547 Kr = 0.2627f; |
| 548 Kb = 0.0593f; |
| 549 break; |
| 550 |
| 551 case ColorSpace::MatrixID::YDZDX: { |
| 552 float data[16] = { |
| 553 0.0f, 1.0f, 0.0f, 0.0f, // Y |
| 554 0.0f, -0.5f, 0.986566f / 2.0f, 0.5f, // DX or DZ |
| 555 0.5f, -0.991902f / 2.0f, 0.0f, 0.5f, // DZ or DX |
| 556 0.0f, 0.0f, 0.0f, 1.0f, |
| 557 }; |
| 558 matrix->setRowMajorf(data); |
| 559 return; |
| 560 } |
| 561 } |
| 562 float Kg = 1.0f - Kr - Kb; |
| 563 float u_m = 0.5f / (1.0f - Kb); |
| 564 float v_m = 0.5f / (1.0f - Kr); |
| 565 float data[16] = { |
| 566 Kr, Kg, Kb, 0.0f, // Y |
| 567 u_m * -Kr, u_m * -Kg, u_m * (1.0f - Kb), 0.5f, // U |
| 568 v_m * (1.0f - Kr), v_m * -Kg, v_m * -Kb, 0.5f, // V |
| 569 0.0f, 0.0f, 0.0f, 1.0f, |
| 570 }; |
| 571 matrix->setRowMajorf(data); |
| 572 } |
| 573 |
| 574 void ColorSpace::GetRangeAdjustMatrix(SkMatrix44* matrix) const { |
| 575 switch (range_) { |
| 576 case RangeID::FULL: |
| 577 case RangeID::UNSPECIFIED: |
| 578 matrix->setIdentity(); |
| 579 return; |
| 580 |
| 581 case RangeID::DERIVED: |
| 582 case RangeID::LIMITED: |
| 583 break; |
| 584 } |
| 585 switch (matrix_) { |
| 586 case MatrixID::RGB: |
| 587 case MatrixID::YCOCG: |
| 588 matrix->setScale(255.0f/219.0f, 255.0f/219.0f, 255.0f/219.0f); |
| 589 matrix->postTranslate(-16.0f/219.0f, -16.0f/219.0f, -16.0f/219.0f); |
| 590 break; |
| 591 |
| 592 case MatrixID::BT709: |
| 593 case MatrixID::UNSPECIFIED: |
| 594 case MatrixID::RESERVED: |
| 595 case MatrixID::FCC: |
| 596 case MatrixID::BT470BG: |
| 597 case MatrixID::SMPTE170M: |
| 598 case MatrixID::SMPTE240M: |
| 599 case MatrixID::BT2020_NCL: |
| 600 case MatrixID::BT2020_CL: |
| 601 case MatrixID::YDZDX: |
| 602 case MatrixID::UNKNOWN: |
| 603 matrix->setScale(255.0f/219.0f, 255.0f/224.0f, 255.0f/224.0f); |
| 604 matrix->postTranslate(-16.0f/219.0f, -15.5f/224.0f, -15.5f/224.0f); |
| 605 break; |
| 606 } |
| 607 } |
| 608 |
483 } // namespace gfx | 609 } // namespace gfx |
OLD | NEW |