| 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 GFX_EXPORT Transform GetPrimaryMatrix(ColorSpace::PrimaryID id) { |
| 33 t.TransformPoint(&color); | 33 SkColorSpacePrimaries primaries = {0}; |
| 34 return color; | |
| 35 } | |
| 36 | |
| 37 ColorTransform::TriStim Xy2xyz(float x, float y) { | |
| 38 return ColorTransform::TriStim(x, y, 1.0f - x - y); | |
| 39 } | |
| 40 | |
| 41 void GetPrimaries(ColorSpace::PrimaryID id, | |
| 42 ColorTransform::TriStim primaries[4]) { | |
| 43 switch (id) { | 34 switch (id) { |
| 44 case ColorSpace::PrimaryID::CUSTOM: | 35 case ColorSpace::PrimaryID::CUSTOM: |
| 45 NOTREACHED(); | 36 NOTREACHED(); |
| 46 | 37 |
| 47 case ColorSpace::PrimaryID::RESERVED0: | 38 case ColorSpace::PrimaryID::RESERVED0: |
| 48 case ColorSpace::PrimaryID::RESERVED: | 39 case ColorSpace::PrimaryID::RESERVED: |
| 49 case ColorSpace::PrimaryID::UNSPECIFIED: | 40 case ColorSpace::PrimaryID::UNSPECIFIED: |
| 50 case ColorSpace::PrimaryID::UNKNOWN: | 41 case ColorSpace::PrimaryID::UNKNOWN: |
| 51 case ColorSpace::PrimaryID::BT709: | 42 case ColorSpace::PrimaryID::BT709: |
| 52 // BT709 is our default case. Put it after the switch just | 43 // 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. | 44 // 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 | 45 // (We don't want to use "default", because we want the compiler |
| 55 // to tell us if we forgot some enum values.) | 46 // to tell us if we forgot some enum values.) |
| 47 primaries.fRX = 0.640f; |
| 48 primaries.fRY = 0.330f; |
| 49 primaries.fGX = 0.300f; |
| 50 primaries.fGY = 0.600f; |
| 51 primaries.fBX = 0.150f; |
| 52 primaries.fBY = 0.060f; |
| 53 primaries.fWX = 0.3127f; |
| 54 primaries.fWY = 0.3290f; |
| 56 break; | 55 break; |
| 57 | 56 |
| 58 case ColorSpace::PrimaryID::BT470M: | 57 case ColorSpace::PrimaryID::BT470M: |
| 59 // Red | 58 primaries.fRX = 0.67f; |
| 60 primaries[0] = Xy2xyz(0.67f, 0.33f); | 59 primaries.fRY = 0.33f; |
| 61 // Green | 60 primaries.fGX = 0.21f; |
| 62 primaries[1] = Xy2xyz(0.21f, 0.71f); | 61 primaries.fGY = 0.71f; |
| 63 // Blue | 62 primaries.fBX = 0.14f; |
| 64 primaries[2] = Xy2xyz(0.14f, 0.08f); | 63 primaries.fBY = 0.08f; |
| 65 // Whitepoint | 64 primaries.fWX = 0.31f; |
| 66 primaries[3] = Xy2xyz(0.31f, 0.316f); | 65 primaries.fWY = 0.316f; |
| 67 return; | 66 break; |
| 68 | 67 |
| 69 case ColorSpace::PrimaryID::BT470BG: | 68 case ColorSpace::PrimaryID::BT470BG: |
| 70 // Red | 69 primaries.fRX = 0.64f; |
| 71 primaries[0] = Xy2xyz(0.64f, 0.33f); | 70 primaries.fRY = 0.33f; |
| 72 // Green | 71 primaries.fGX = 0.29f; |
| 73 primaries[1] = Xy2xyz(0.29f, 0.60f); | 72 primaries.fGY = 0.60f; |
| 74 // Blue | 73 primaries.fBX = 0.15f; |
| 75 primaries[2] = Xy2xyz(0.15f, 0.06f); | 74 primaries.fBY = 0.06f; |
| 76 // Whitepoint (D65f) | 75 primaries.fWX = 0.3127f; |
| 77 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 76 primaries.fWY = 0.3290f; |
| 78 return; | 77 break; |
| 79 | 78 |
| 80 case ColorSpace::PrimaryID::SMPTE170M: | 79 case ColorSpace::PrimaryID::SMPTE170M: |
| 81 case ColorSpace::PrimaryID::SMPTE240M: | 80 case ColorSpace::PrimaryID::SMPTE240M: |
| 82 // Red | 81 primaries.fRX = 0.630f; |
| 83 primaries[0] = Xy2xyz(0.630f, 0.340f); | 82 primaries.fRY = 0.340f; |
| 84 // Green | 83 primaries.fGX = 0.310f; |
| 85 primaries[1] = Xy2xyz(0.310f, 0.595f); | 84 primaries.fGY = 0.595f; |
| 86 // Blue | 85 primaries.fBX = 0.155f; |
| 87 primaries[2] = Xy2xyz(0.155f, 0.070f); | 86 primaries.fBY = 0.070f; |
| 88 // Whitepoint (D65f) | 87 primaries.fWX = 0.3127f; |
| 89 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 88 primaries.fWY = 0.3290f; |
| 90 return; | 89 break; |
| 91 | 90 |
| 92 case ColorSpace::PrimaryID::FILM: | 91 case ColorSpace::PrimaryID::FILM: |
| 93 // Red | 92 primaries.fRX = 0.681f; |
| 94 primaries[0] = Xy2xyz(0.681f, 0.319f); | 93 primaries.fRY = 0.319f; |
| 95 // Green | 94 primaries.fGX = 0.243f; |
| 96 primaries[1] = Xy2xyz(0.243f, 0.692f); | 95 primaries.fGY = 0.692f; |
| 97 // Blue | 96 primaries.fBX = 0.145f; |
| 98 primaries[2] = Xy2xyz(0.145f, 0.049f); | 97 primaries.fBY = 0.049f; |
| 99 // Whitepoint (Cf) | 98 primaries.fWX = 0.310f; |
| 100 primaries[3] = Xy2xyz(0.310f, 0.136f); | 99 primaries.fWY = 0.136f; |
| 101 return; | 100 break; |
| 102 | 101 |
| 103 case ColorSpace::PrimaryID::BT2020: | 102 case ColorSpace::PrimaryID::BT2020: |
| 104 // Red | 103 primaries.fRX = 0.708f; |
| 105 primaries[0] = Xy2xyz(0.708f, 0.292f); | 104 primaries.fRY = 0.292f; |
| 106 // Green | 105 primaries.fGX = 0.170f; |
| 107 primaries[1] = Xy2xyz(0.170f, 0.797f); | 106 primaries.fGY = 0.797f; |
| 108 // Blue | 107 primaries.fBX = 0.131f; |
| 109 primaries[2] = Xy2xyz(0.131f, 0.046f); | 108 primaries.fBY = 0.046f; |
| 110 // Whitepoint (D65f) | 109 primaries.fWX = 0.3127f; |
| 111 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 110 primaries.fWY = 0.3290f; |
| 112 return; | 111 break; |
| 113 | 112 |
| 114 case ColorSpace::PrimaryID::SMPTEST428_1: | 113 case ColorSpace::PrimaryID::SMPTEST428_1: |
| 115 // X | 114 primaries.fRX = 1.0f; |
| 116 primaries[0] = Xy2xyz(1.0f, 0.0f); | 115 primaries.fRY = 0.0f; |
| 117 // Y | 116 primaries.fGX = 0.0f; |
| 118 primaries[1] = Xy2xyz(0.0f, 1.0f); | 117 primaries.fGY = 1.0f; |
| 119 // Z | 118 primaries.fBX = 0.0f; |
| 120 primaries[2] = Xy2xyz(0.0f, 0.0f); | 119 primaries.fBY = 0.0f; |
| 121 // Whitepoint (Ef) | 120 primaries.fWX = 1.0f / 3.0f; |
| 122 primaries[3] = Xy2xyz(1.0f / 3.0f, 1.0f / 3.0f); | 121 primaries.fWY = 1.0f / 3.0f; |
| 123 return; | 122 break; |
| 124 | 123 |
| 125 case ColorSpace::PrimaryID::SMPTEST431_2: | 124 case ColorSpace::PrimaryID::SMPTEST431_2: |
| 126 // Red | 125 primaries.fRX = 0.680f; |
| 127 primaries[0] = Xy2xyz(0.680f, 0.320f); | 126 primaries.fRY = 0.320f; |
| 128 // Green | 127 primaries.fGX = 0.265f; |
| 129 primaries[1] = Xy2xyz(0.265f, 0.690f); | 128 primaries.fGY = 0.690f; |
| 130 // Blue | 129 primaries.fBX = 0.150f; |
| 131 primaries[2] = Xy2xyz(0.150f, 0.060f); | 130 primaries.fBY = 0.060f; |
| 132 // Whitepoint | 131 primaries.fWX = 0.314f; |
| 133 primaries[3] = Xy2xyz(0.314f, 0.351f); | 132 primaries.fWY = 0.351f; |
| 134 return; | 133 break; |
| 135 | 134 |
| 136 case ColorSpace::PrimaryID::SMPTEST432_1: | 135 case ColorSpace::PrimaryID::SMPTEST432_1: |
| 137 // Red | 136 primaries.fRX = 0.680f; |
| 138 primaries[0] = Xy2xyz(0.680f, 0.320f); | 137 primaries.fRY = 0.320f; |
| 139 // Green | 138 primaries.fGX = 0.265f; |
| 140 primaries[1] = Xy2xyz(0.265f, 0.690f); | 139 primaries.fGY = 0.690f; |
| 141 // Blue | 140 primaries.fBX = 0.150f; |
| 142 primaries[2] = Xy2xyz(0.150f, 0.060f); | 141 primaries.fBY = 0.060f; |
| 143 // Whitepoint (D65f) | 142 primaries.fWX = 0.3127f; |
| 144 primaries[3] = Xy2xyz(0.3127f, 0.3290f); | 143 primaries.fWY = 0.3290f; |
| 145 return; | 144 break; |
| 146 | 145 |
| 147 case ColorSpace::PrimaryID::XYZ_D50: | 146 case ColorSpace::PrimaryID::XYZ_D50: |
| 148 // X | 147 primaries.fRX = 1.0f; |
| 149 primaries[0] = Xy2xyz(1.0f, 0.0f); | 148 primaries.fRY = 0.0f; |
| 150 // Y | 149 primaries.fGX = 0.0f; |
| 151 primaries[1] = Xy2xyz(0.0f, 1.0f); | 150 primaries.fGY = 1.0f; |
| 152 // Z | 151 primaries.fBX = 0.0f; |
| 153 primaries[2] = Xy2xyz(0.0f, 0.0f); | 152 primaries.fBY = 0.0f; |
| 154 // D50 | 153 primaries.fWX = 0.34567f; |
| 155 primaries[3] = Xy2xyz(0.34567f, 0.35850f); | 154 primaries.fWY = 0.35850f; |
| 156 return; | 155 break; |
| 157 } | 156 } |
| 158 | 157 |
| 159 // Red | 158 SkMatrix44 matrix; |
| 160 primaries[0] = Xy2xyz(0.640f, 0.330f); | 159 primaries.toXYZD50(&matrix); |
| 161 // Green | 160 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 } | 161 } |
| 201 | 162 |
| 202 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) { | 163 GFX_EXPORT float FromLinear(ColorSpace::TransferID id, float v) { |
| 203 switch (id) { | 164 switch (id) { |
| 204 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: | 165 case ColorSpace::TransferID::SMPTEST2084_NON_HDR: |
| 205 // Should already be handled. | 166 // Should already be handled. |
| 206 NOTREACHED(); | 167 NOTREACHED(); |
| 207 case ColorSpace::TransferID::CUSTOM: | 168 case ColorSpace::TransferID::CUSTOM: |
| 208 // TODO(hubbe): Actually implement custom transfer functions. | 169 // TODO(hubbe): Actually implement custom transfer functions. |
| 209 case ColorSpace::TransferID::RESERVED0: | 170 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); | 1018 to_profile ? ColorSpace::CreateXYZD50() : to, intent, &builder); |
| 1058 if (to_profile) { | 1019 if (to_profile) { |
| 1059 builder.Append(std::unique_ptr<ColorTransformInternal>( | 1020 builder.Append(std::unique_ptr<ColorTransformInternal>( |
| 1060 new QCMSColorTransform(GetXYZD50Profile(), to_profile))); | 1021 new QCMSColorTransform(GetXYZD50Profile(), to_profile))); |
| 1061 } | 1022 } |
| 1062 | 1023 |
| 1063 return builder.GetTransform(); | 1024 return builder.GetTransform(); |
| 1064 } | 1025 } |
| 1065 | 1026 |
| 1066 } // namespace gfx | 1027 } // namespace gfx |
| OLD | NEW |