Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2016 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_transform.h" | 5 #include "ui/gfx/color_transform.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 namespace gfx { | 22 namespace gfx { |
| 23 | 23 |
| 24 Transform Invert(const Transform& t) { | 24 Transform Invert(const Transform& t) { |
| 25 Transform ret = t; | 25 Transform ret = t; |
| 26 if (!t.GetInverse(&ret)) { | 26 if (!t.GetInverse(&ret)) { |
| 27 LOG(ERROR) << "Inverse should alsways be possible."; | 27 LOG(ERROR) << "Inverse should alsways be possible."; |
| 28 } | 28 } |
| 29 return ret; | 29 return ret; |
| 30 } | 30 } |
| 31 | 31 |
| 32 ColorTransform::TriStim Map(const Transform& t, ColorTransform::TriStim color) { | 32 void GetPrimaries(ColorSpace::PrimaryID id, |
|
hubbe
2017/01/20 20:15:27
Remove?
ccameron
2017/01/20 23:26:16
Done.
| |
| 33 t.TransformPoint(&color); | 33 SkColorSpacePrimaries* primaries) { |
| 34 return color; | |
| 35 } | 34 } |
| 36 | 35 |
| 37 ColorTransform::TriStim Xy2xyz(float x, float y) { | 36 GFX_EXPORT Transform GetPrimaryMatrix(ColorSpace::PrimaryID id) { |
| 38 return ColorTransform::TriStim(x, y, 1.0f - x - y); | 37 SkColorSpacePrimaries primaries = {0}; |
| 39 } | |
| 40 | |
| 41 void GetPrimaries(ColorSpace::PrimaryID id, | |
| 42 ColorTransform::TriStim primaries[4]) { | |
| 43 switch (id) { | 38 switch (id) { |
| 44 case ColorSpace::PrimaryID::CUSTOM: | 39 case ColorSpace::PrimaryID::CUSTOM: |
| 45 NOTREACHED(); | 40 NOTREACHED(); |
| 46 | 41 |
| 47 case ColorSpace::PrimaryID::RESERVED0: | 42 case ColorSpace::PrimaryID::RESERVED0: |
| 48 case ColorSpace::PrimaryID::RESERVED: | 43 case ColorSpace::PrimaryID::RESERVED: |
| 49 case ColorSpace::PrimaryID::UNSPECIFIED: | 44 case ColorSpace::PrimaryID::UNSPECIFIED: |
| 50 case ColorSpace::PrimaryID::UNKNOWN: | 45 case ColorSpace::PrimaryID::UNKNOWN: |
| 51 case ColorSpace::PrimaryID::BT709: | 46 case ColorSpace::PrimaryID::BT709: |
| 52 // BT709 is our default case. Put it after the switch just | 47 // BT709 is our default case. Put it after the switch just |
| 53 // in case we somehow get an id which is not listed in the switch. | 48 // in case we somehow get an id which is not listed in the switch. |
| 54 // (We don't want to use "default", because we want the compiler | 49 // (We don't want to use "default", because we want the compiler |
| 55 // to tell us if we forgot some enum values.) | 50 // to tell us if we forgot some enum values.) |
| 51 primaries.fRX = 0.640f; | |
| 52 primaries.fRY = 0.330f; | |
| 53 primaries.fGX = 0.300f; | |
| 54 primaries.fGY = 0.600f; | |
| 55 primaries.fBX = 0.150f; | |
| 56 primaries.fBY = 0.060f; | |
| 57 primaries.fWX = 0.3127f; | |
| 58 primaries.fWY = 0.3290f; | |
| 56 break; | 59 break; |
| 57 | 60 |
| 58 case ColorSpace::PrimaryID::BT470M: | 61 case ColorSpace::PrimaryID::BT470M: |
| 59 // Red | 62 primaries.fRX = 0.67f; |
| 60 primaries[0] = Xy2xyz(0.67f, 0.33f); | 63 primaries.fRY = 0.33f; |
| 61 // Green | 64 primaries.fGX = 0.21f; |
| 62 primaries[1] = Xy2xyz(0.21f, 0.71f); | 65 primaries.fGY = 0.71f; |
| 63 // Blue | 66 primaries.fBX = 0.14f; |
| 64 primaries[2] = Xy2xyz(0.14f, 0.08f); | 67 primaries.fBY = 0.08f; |
| 65 // Whitepoint | 68 primaries.fWX = 0.31f; |
| 66 primaries[3] = Xy2xyz(0.31f, 0.316f); | 69 primaries.fWY = 0.316f; |
| 67 return; | 70 break; |
| 68 | 71 |
| 69 case ColorSpace::PrimaryID::BT470BG: | 72 case ColorSpace::PrimaryID::BT470BG: |
| 70 // Red | 73 primaries.fRX = 0.64f; |
| 71 primaries[0] = Xy2xyz(0.64f, 0.33f); | 74 primaries.fRY = 0.33f; |
| 72 // Green | 75 primaries.fGX = 0.29f; |
| 73 primaries[1] = Xy2xyz(0.29f, 0.60f); | 76 primaries.fGY = 0.60f; |
| 74 // Blue | 77 primaries.fBX = 0.15f; |
| 75 primaries[2] = Xy2xyz(0.15f, 0.06f); | 78 primaries.fBY = 0.06f; |
| 76 // Whitepoint (D65f) | 79 primaries.fWX = 0.3127f; |
| 77 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 80 primaries.fWY = 0.3290f; |
| 78 return; | 81 break; |
| 79 | 82 |
| 80 case ColorSpace::PrimaryID::SMPTE170M: | 83 case ColorSpace::PrimaryID::SMPTE170M: |
| 81 case ColorSpace::PrimaryID::SMPTE240M: | 84 case ColorSpace::PrimaryID::SMPTE240M: |
| 82 // Red | 85 primaries.fRX = 0.630f; |
| 83 primaries[0] = Xy2xyz(0.630f, 0.340f); | 86 primaries.fRY = 0.340f; |
| 84 // Green | 87 primaries.fGX = 0.310f; |
| 85 primaries[1] = Xy2xyz(0.310f, 0.595f); | 88 primaries.fGY = 0.595f; |
| 86 // Blue | 89 primaries.fBX = 0.155f; |
| 87 primaries[2] = Xy2xyz(0.155f, 0.070f); | 90 primaries.fBY = 0.070f; |
| 88 // Whitepoint (D65f) | 91 primaries.fWX = 0.3127f; |
| 89 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 92 primaries.fWY = 0.3290f; |
| 90 return; | 93 break; |
| 91 | 94 |
| 92 case ColorSpace::PrimaryID::FILM: | 95 case ColorSpace::PrimaryID::FILM: |
| 93 // Red | 96 primaries.fRX = 0.681f; |
| 94 primaries[0] = Xy2xyz(0.681f, 0.319f); | 97 primaries.fRY = 0.319f; |
| 95 // Green | 98 primaries.fGX = 0.243f; |
| 96 primaries[1] = Xy2xyz(0.243f, 0.692f); | 99 primaries.fGY = 0.692f; |
| 97 // Blue | 100 primaries.fBX = 0.145f; |
| 98 primaries[2] = Xy2xyz(0.145f, 0.049f); | 101 primaries.fBY = 0.049f; |
| 99 // Whitepoint (Cf) | 102 primaries.fWX = 0.310f; |
| 100 primaries[3] = Xy2xyz(0.310f, 0.136f); | 103 primaries.fWY = 0.136f; |
| 101 return; | 104 break; |
| 102 | 105 |
| 103 case ColorSpace::PrimaryID::BT2020: | 106 case ColorSpace::PrimaryID::BT2020: |
| 104 // Red | 107 primaries.fRX = 0.708f; |
| 105 primaries[0] = Xy2xyz(0.708f, 0.292f); | 108 primaries.fRY = 0.292f; |
| 106 // Green | 109 primaries.fGX = 0.170f; |
| 107 primaries[1] = Xy2xyz(0.170f, 0.797f); | 110 primaries.fGY = 0.797f; |
| 108 // Blue | 111 primaries.fBX = 0.131f; |
| 109 primaries[2] = Xy2xyz(0.131f, 0.046f); | 112 primaries.fBY = 0.046f; |
| 110 // Whitepoint (D65f) | 113 primaries.fWX = 0.3127f; |
| 111 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 114 primaries.fWY = 0.3290f; |
| 112 return; | 115 break; |
| 113 | 116 |
| 114 case ColorSpace::PrimaryID::SMPTEST428_1: | 117 case ColorSpace::PrimaryID::SMPTEST428_1: |
| 115 // X | 118 primaries.fRX = 1.0f; |
| 116 primaries[0] = Xy2xyz(1.0f, 0.0f); | 119 primaries.fRY = 0.0f; |
| 117 // Y | 120 primaries.fGX = 0.0f; |
| 118 primaries[1] = Xy2xyz(0.0f, 1.0f); | 121 primaries.fGY = 1.0f; |
| 119 // Z | 122 primaries.fBX = 0.0f; |
| 120 primaries[2] = Xy2xyz(0.0f, 0.0f); | 123 primaries.fBY = 0.0f; |
| 121 // Whitepoint (Ef) | 124 primaries.fWX = 1.0f / 3.0f; |
| 122 primaries[3] = Xy2xyz(1.0f / 3.0f, 1.0f / 3.0f); | 125 primaries.fWY = 1.0f / 3.0f; |
| 123 return; | 126 break; |
| 124 | 127 |
| 125 case ColorSpace::PrimaryID::SMPTEST431_2: | 128 case ColorSpace::PrimaryID::SMPTEST431_2: |
| 126 // Red | 129 primaries.fRX = 0.680f; |
| 127 primaries[0] = Xy2xyz(0.680f, 0.320f); | 130 primaries.fRY = 0.320f; |
| 128 // Green | 131 primaries.fGX = 0.265f; |
| 129 primaries[1] = Xy2xyz(0.265f, 0.690f); | 132 primaries.fGY = 0.690f; |
| 130 // Blue | 133 primaries.fBX = 0.150f; |
| 131 primaries[2] = Xy2xyz(0.150f, 0.060f); | 134 primaries.fBY = 0.060f; |
| 132 // Whitepoint | 135 primaries.fWX = 0.314f; |
| 133 primaries[3] = Xy2xyz(0.314f, 0.351f); | 136 primaries.fWY = 0.351f; |
| 134 return; | 137 break; |
| 135 | 138 |
| 136 case ColorSpace::PrimaryID::SMPTEST432_1: | 139 case ColorSpace::PrimaryID::SMPTEST432_1: |
| 137 // Red | 140 primaries.fRX = 0.680f; |
| 138 primaries[0] = Xy2xyz(0.680f, 0.320f); | 141 primaries.fRY = 0.320f; |
| 139 // Green | 142 primaries.fGX = 0.265f; |
| 140 primaries[1] = Xy2xyz(0.265f, 0.690f); | 143 primaries.fGY = 0.690f; |
| 141 // Blue | 144 primaries.fBX = 0.150f; |
| 142 primaries[2] = Xy2xyz(0.150f, 0.060f); | 145 primaries.fBY = 0.060f; |
| 143 // Whitepoint (D65f) | 146 primaries.fWX = 0.3127f; |
| 144 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 147 primaries.fWY = 0.3290f; |
| 145 return; | 148 break; |
| 146 | 149 |
| 147 case ColorSpace::PrimaryID::XYZ_D50: | 150 case ColorSpace::PrimaryID::XYZ_D50: |
| 148 // X | 151 primaries.fRX = 1.0f; |
| 149 primaries[0] = Xy2xyz(1.0f, 0.0f); | 152 primaries.fRY = 0.0f; |
| 150 // Y | 153 primaries.fGX = 0.0f; |
| 151 primaries[1] = Xy2xyz(0.0f, 1.0f); | 154 primaries.fGY = 1.0f; |
| 152 // Z | 155 primaries.fBX = 0.0f; |
| 153 primaries[2] = Xy2xyz(0.0f, 0.0f); | 156 primaries.fBY = 0.0f; |
| 154 // D50 | 157 primaries.fWX = 0.34567f; |
| 155 primaries[3] = Xy2xyz(0.34567f, 0.35850f); | 158 primaries.fWY = 0.35850f; |
| 156 return; | 159 break; |
| 157 } | 160 } |
| 158 | 161 |
| 159 // Red | 162 SkMatrix44 matrix; |
| 160 primaries[0] = Xy2xyz(0.640f, 0.330f); | 163 primaries.toXYZD50(&matrix); |
|
hubbe
2017/01/20 20:15:27
I assume that this doe the same chromatic adaptati
ccameron
2017/01/20 23:26:16
Yes, see the implementation at:
https://cs.chromiu
hubbe
2017/01/20 23:28:15
looks good (but a test would have been even better
| |
| 161 // Green | 164 return Transform(matrix); |
| 162 primaries[1] = Xy2xyz(0.300f, 0.600f); | |
| 163 // Blue | |
| 164 primaries[2] = Xy2xyz(0.150f, 0.060f); | |
| 165 // Whitepoint (D65f) | |
| 166 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | |
| 167 } | |
| 168 | |
| 169 GFX_EXPORT Transform GetPrimaryMatrix(ColorSpace::PrimaryID id) { | |
| 170 ColorTransform::TriStim primaries[4]; | |
| 171 GetPrimaries(id, primaries); | |
| 172 ColorTransform::TriStim WXYZ(primaries[3].x() / primaries[3].y(), 1.0f, | |
| 173 primaries[3].z() / primaries[3].y()); | |
| 174 | |
| 175 Transform ret( | |
| 176 primaries[0].x(), primaries[1].x(), primaries[2].x(), 0.0f, // 1 | |
| 177 primaries[0].y(), primaries[1].y(), primaries[2].y(), 0.0f, // 2 | |
| 178 primaries[0].z(), primaries[1].z(), primaries[2].z(), 0.0f, // 3 | |
| 179 0.0f, 0.0f, 0.0f, 1.0f); // 4 | |
| 180 | |
| 181 ColorTransform::TriStim conv = Map(Invert(ret), WXYZ); | |
| 182 ret.Scale3d(conv.x(), conv.y(), conv.z()); | |
| 183 | |
| 184 // Chromatic adaptation. | |
| 185 Transform bradford(0.8951000f, 0.2664000f, -0.1614000f, 0.0f, // 1 | |
| 186 -0.7502000f, 1.7135000f, 0.0367000f, 0.0f, // 2 | |
| 187 0.0389000f, -0.0685000f, 1.0296000f, 0.0f, // 3 | |
| 188 0.0f, 0.0f, 0.0f, 1.0f); // 4 | |
| 189 | |
| 190 ColorTransform::TriStim D50(0.9642f, 1.0f, 0.8249f); | |
| 191 ColorTransform::TriStim source_response = Map(bradford, WXYZ); | |
| 192 ColorTransform::TriStim dest_response = Map(bradford, D50); | |
| 193 | |
| 194 Transform adapter; | |
| 195 adapter.Scale3d(dest_response.x() / source_response.x(), | |
| 196 dest_response.y() / source_response.y(), | |
| 197 dest_response.z() / source_response.z()); | |
| 198 | |
| 199 return Invert(bradford) * adapter * bradford * ret; | |
| 200 } | 165 } |
| 201 | 166 |
| 202 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) { | 167 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) { |
| 203 switch (id) { | 168 switch (id) { |
| 204 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: | 169 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: |
| 205 // Should already be handled. | 170 // Should already be handled. |
| 206 NOTREACHED(); | 171 NOTREACHED(); |
| 207 case ColorSpace::TransferID::CUSTOM: | 172 case ColorSpace::TransferID::CUSTOM: |
| 208 // TODO(hubbe): Actually implement custom transfer functions. | 173 // TODO(hubbe): Actually implement custom transfer functions. |
| 209 case ColorSpace::TransferID::RESERVED0: | 174 case ColorSpace::TransferID::RESERVED0: |
| (...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1057 to_profile ? ColorSpace::CreateXYZD50() : to, intent, &builder); | 1022 to_profile ? ColorSpace::CreateXYZD50() : to, intent, &builder); |
| 1058 if (to_profile) { | 1023 if (to_profile) { |
| 1059 builder.Append(std::unique_ptr<ColorTransformInternal>( | 1024 builder.Append(std::unique_ptr<ColorTransformInternal>( |
| 1060 new QCMSColorTransform(GetXYZD50Profile(), to_profile))); | 1025 new QCMSColorTransform(GetXYZD50Profile(), to_profile))); |
| 1061 } | 1026 } |
| 1062 | 1027 |
| 1063 return builder.GetTransform(); | 1028 return builder.GetTransform(); |
| 1064 } | 1029 } |
| 1065 | 1030 |
| 1066 } // namespace gfx | 1031 } // namespace gfx |
| OLD | NEW |