Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 <stdlib.h> | 5 #include <stdlib.h> |
| 6 | 6 |
| 7 #include <algorithm> | |
| 8 #include <limits> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 7 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 8 #include "third_party/skia/include/core/SkBitmap.h" | 12 #include "third_party/skia/include/core/SkBitmap.h" |
| 9 #include "third_party/skia/include/core/SkColorPriv.h" | 13 #include "third_party/skia/include/core/SkColorPriv.h" |
| 14 #include "ui/gfx/canvas.h" | |
| 10 #include "ui/gfx/color_utils.h" | 15 #include "ui/gfx/color_utils.h" |
| 11 | 16 |
| 17 namespace { | |
| 18 | |
| 19 void Calculate8bitBitmapMinMax(const SkBitmap& bitmap, | |
| 20 uint8_t* min_gl, | |
| 21 uint8_t* max_gl) { | |
| 22 // Compute minimal and maximal graylevel (or alphalevel) of the input | |
| 23 // |bitmap|. |bitmap| has to be allocated and configured to kA8_Config. | |
|
Alexei Svitkine (slow)
2013/02/21 19:49:33
Nit: move comment above function
motek.
2013/02/21 22:45:03
Done.
| |
| 24 SkAutoLockPixels bitmap_lock(bitmap); | |
| 25 DCHECK(bitmap.getPixels()); | |
| 26 DCHECK(bitmap.config() == SkBitmap::kA8_Config); | |
| 27 DCHECK(min_gl); | |
| 28 DCHECK(max_gl); | |
| 29 *min_gl = std::numeric_limits<uint8_t>::max(); | |
| 30 *max_gl = std::numeric_limits<uint8_t>::min(); | |
| 31 for (int y = 0; y < bitmap.height(); ++y) { | |
| 32 uint8_t* current_color = bitmap.getAddr8(0, y); | |
| 33 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { | |
| 34 *min_gl = std::min(*min_gl, *current_color); | |
| 35 *max_gl = std::max(*max_gl, *current_color); | |
| 36 } | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 } // namespace | |
| 41 | |
| 12 TEST(ColorUtils, SkColorToHSLRed) { | 42 TEST(ColorUtils, SkColorToHSLRed) { |
| 13 color_utils::HSL hsl = { 0, 0, 0 }; | 43 color_utils::HSL hsl = { 0, 0, 0 }; |
| 14 color_utils::SkColorToHSL(SK_ColorRED, &hsl); | 44 color_utils::SkColorToHSL(SK_ColorRED, &hsl); |
| 15 EXPECT_DOUBLE_EQ(hsl.h, 0); | 45 EXPECT_DOUBLE_EQ(hsl.h, 0); |
| 16 EXPECT_DOUBLE_EQ(hsl.s, 1); | 46 EXPECT_DOUBLE_EQ(hsl.s, 1); |
| 17 EXPECT_DOUBLE_EQ(hsl.l, 0.5); | 47 EXPECT_DOUBLE_EQ(hsl.l, 0.5); |
| 18 } | 48 } |
| 19 | 49 |
| 20 TEST(ColorUtils, SkColorToHSLGrey) { | 50 TEST(ColorUtils, SkColorToHSLGrey) { |
| 21 color_utils::HSL hsl = { 0, 0, 0 }; | 51 color_utils::HSL hsl = { 0, 0, 0 }; |
| 22 color_utils::SkColorToHSL(SkColorSetARGB(255, 128, 128, 128), &hsl); | 52 color_utils::SkColorToHSL(SkColorSetARGB(255, 128, 128, 128), &hsl); |
| 23 EXPECT_DOUBLE_EQ(hsl.h, 0); | 53 EXPECT_DOUBLE_EQ(hsl.h, 0); |
| 24 EXPECT_DOUBLE_EQ(hsl.s, 0); | 54 EXPECT_DOUBLE_EQ(hsl.s, 0); |
| 25 EXPECT_EQ(static_cast<int>(hsl.l * 100), | 55 EXPECT_EQ(static_cast<int>(hsl.l * 100), |
| 26 static_cast<int>(0.5 * 100)); // Accurate to two decimal places. | 56 static_cast<int>(0.5 * 100)); // Accurate to two decimal places. |
| 27 } | 57 } |
| 28 | 58 |
| 29 TEST(ColorUtils, HSLToSkColorWithAlpha) { | 59 TEST(ColorUtils, HSLToSkColorWithAlpha) { |
| 30 SkColor red = SkColorSetARGB(128, 255, 0, 0); | 60 SkColor red = SkColorSetARGB(128, 255, 0, 0); |
| 31 color_utils::HSL hsl = { 0, 1, 0.5 }; | 61 color_utils::HSL hsl = { 0, 1, 0.5 }; |
| 32 SkColor result = color_utils::HSLToSkColor(hsl, 128); | 62 SkColor result = color_utils::HSLToSkColor(hsl, 128); |
| 33 EXPECT_EQ(SkColorGetA(red), SkColorGetA(result)); | 63 EXPECT_EQ(SkColorGetA(red), SkColorGetA(result)); |
| 34 EXPECT_EQ(SkColorGetR(red), SkColorGetR(result)); | 64 EXPECT_EQ(SkColorGetR(red), SkColorGetR(result)); |
| 35 EXPECT_EQ(SkColorGetG(red), SkColorGetG(result)); | 65 EXPECT_EQ(SkColorGetG(red), SkColorGetG(result)); |
| 36 EXPECT_EQ(SkColorGetB(red), SkColorGetB(result)); | 66 EXPECT_EQ(SkColorGetB(red), SkColorGetB(result)); |
| 37 } | 67 } |
| 38 | 68 |
| 39 | |
| 40 TEST(ColorUtils, RGBtoHSLRoundTrip) { | 69 TEST(ColorUtils, RGBtoHSLRoundTrip) { |
| 41 // Just spot check values near the edges. | 70 // Just spot check values near the edges. |
| 42 for (int r = 0; r < 10; ++r) { | 71 for (int r = 0; r < 10; ++r) { |
| 43 for (int g = 0; g < 10; ++g) { | 72 for (int g = 0; g < 10; ++g) { |
| 44 for (int b = 0; b < 10; ++b) { | 73 for (int b = 0; b < 10; ++b) { |
| 45 SkColor rgb = SkColorSetARGB(255, r, g, b); | 74 SkColor rgb = SkColorSetARGB(255, r, g, b); |
| 46 color_utils::HSL hsl = { 0, 0, 0 }; | 75 color_utils::HSL hsl = { 0, 0, 0 }; |
| 47 color_utils::SkColorToHSL(rgb, &hsl); | 76 color_utils::SkColorToHSL(rgb, &hsl); |
| 48 SkColor out = color_utils::HSLToSkColor(hsl, 255); | 77 SkColor out = color_utils::HSLToSkColor(hsl, 255); |
| 49 EXPECT_EQ(SkColorGetR(out), SkColorGetR(rgb)); | 78 EXPECT_EQ(SkColorGetR(out), SkColorGetR(rgb)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 back); | 120 back); |
| 92 | 121 |
| 93 // One is fully transparent, result is partially transparent. | 122 // One is fully transparent, result is partially transparent. |
| 94 back = SkColorSetA(back, 0); | 123 back = SkColorSetA(back, 0); |
| 95 EXPECT_EQ(136U, SkColorGetA(color_utils::AlphaBlend(fore, back, 136))); | 124 EXPECT_EQ(136U, SkColorGetA(color_utils::AlphaBlend(fore, back, 136))); |
| 96 | 125 |
| 97 // Both are fully transparent, result is fully transparent. | 126 // Both are fully transparent, result is fully transparent. |
| 98 fore = SkColorSetA(fore, 0); | 127 fore = SkColorSetA(fore, 0); |
| 99 EXPECT_EQ(0U, SkColorGetA(color_utils::AlphaBlend(fore, back, 255))); | 128 EXPECT_EQ(0U, SkColorGetA(color_utils::AlphaBlend(fore, back, 255))); |
| 100 } | 129 } |
| 130 | |
| 131 TEST(ColorUtils, ApplyColorReductionSingleColor) { | |
| 132 // The test runs color reduction on a single-colot image, where results are | |
| 133 // bound to be uninteresting. This is an important edge case, though. | |
| 134 SkBitmap source, result; | |
| 135 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); | |
| 136 result.setConfig(SkBitmap::kA8_Config, 300, 200); | |
| 137 | |
| 138 source.allocPixels(); | |
| 139 result.allocPixels(); | |
| 140 source.eraseRGB(50, 150, 200); | |
| 141 | |
| 142 gfx::Vector3dF transform(1.0f, .5f, 0.1f); | |
| 143 // This transform, if not scaled, should result in GL=145. | |
| 144 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 145 source, transform, false, &result)); | |
| 146 | |
| 147 uint8_t min_gl = 0; | |
| 148 uint8_t max_gl = 0; | |
| 149 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 150 EXPECT_EQ(145, min_gl); | |
| 151 EXPECT_EQ(145, max_gl); | |
| 152 | |
| 153 // Now scan requesting rescale. Expect all 0. | |
| 154 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 155 source, transform, true, &result)); | |
| 156 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 157 EXPECT_EQ(0, min_gl); | |
| 158 EXPECT_EQ(0, max_gl); | |
| 159 | |
| 160 // Test cliping to upper limit. | |
| 161 transform.set_z(1.1f); | |
| 162 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 163 source, transform, false, &result)); | |
| 164 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 165 EXPECT_EQ(0xFF, min_gl); | |
| 166 EXPECT_EQ(0xFF, max_gl); | |
| 167 | |
| 168 // Test cliping to upper limit. | |
| 169 transform.Scale(-1.0f); | |
| 170 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 171 source, transform, false, &result)); | |
| 172 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 173 EXPECT_EQ(0x0, min_gl); | |
| 174 EXPECT_EQ(0x0, max_gl); | |
| 175 } | |
| 176 | |
| 177 TEST(ColorUtils, ApplyColorReductionBlackAndWhite) { | |
| 178 // Check with images with multiple colors. This is really different only when | |
| 179 // the result is scaled. | |
| 180 gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true); | |
| 181 | |
| 182 // The image consists of vertical non-overlapping stripes 150 pixels wide. | |
| 183 canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0)); | |
| 184 canvas.FillRect(gfx::Rect(150, 0, 150, 200), SkColorSetRGB(255, 255, 255)); | |
| 185 SkBitmap source = | |
| 186 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | |
| 187 SkBitmap result; | |
| 188 result.setConfig(SkBitmap::kA8_Config, 300, 200); | |
| 189 result.allocPixels(); | |
| 190 | |
| 191 | |
| 192 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); | |
| 193 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 194 source, transform, true, &result)); | |
| 195 uint8_t min_gl = 0; | |
| 196 uint8_t max_gl = 0; | |
| 197 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 198 | |
| 199 EXPECT_EQ(0, min_gl); | |
| 200 EXPECT_EQ(255, max_gl); | |
| 201 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); | |
| 202 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); | |
| 203 | |
| 204 // Reverse test. | |
| 205 transform.Scale(-1.0f); | |
| 206 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 207 source, transform, true, &result)); | |
| 208 min_gl = 0; | |
| 209 max_gl = 0; | |
| 210 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 211 | |
| 212 EXPECT_EQ(0, min_gl); | |
| 213 EXPECT_EQ(255, max_gl); | |
| 214 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(0, 0))); | |
| 215 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | |
| 216 } | |
| 217 | |
| 218 TEST(ColorUtils, ApplyColorReductionMultiColor) { | |
| 219 // Check with images with multiple colors. This is really different only when | |
| 220 // the result is scaled. | |
| 221 gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true); | |
| 222 | |
| 223 // The image consists of vertical non-overlapping stripes 100 pixels wide. | |
| 224 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0)); | |
| 225 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(0, 255, 0)); | |
| 226 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(0, 0, 128)); | |
| 227 SkBitmap source = | |
| 228 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | |
| 229 SkBitmap result; | |
| 230 result.setConfig(SkBitmap::kA8_Config, 300, 200); | |
| 231 result.allocPixels(); | |
| 232 | |
| 233 | |
| 234 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); | |
| 235 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 236 source, transform, false, &result)); | |
| 237 uint8_t min_gl = 0; | |
| 238 uint8_t max_gl = 0; | |
| 239 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 240 EXPECT_EQ(12, min_gl); | |
| 241 EXPECT_EQ(127, max_gl); | |
| 242 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | |
| 243 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); | |
| 244 EXPECT_EQ(100U, SkColorGetA(result.getColor(0, 0))); | |
| 245 | |
| 246 EXPECT_TRUE(color_utils::ApplyColorReduction( | |
| 247 source, transform, true, &result)); | |
| 248 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 249 EXPECT_EQ(0, min_gl); | |
| 250 EXPECT_EQ(255, max_gl); | |
| 251 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | |
| 252 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); | |
| 253 EXPECT_EQ(193U, SkColorGetA(result.getColor(0, 0))); | |
| 254 } | |
| 255 | |
| 256 TEST(ColorUtils, ComputePrincipalComponentImageNotComputable) { | |
| 257 SkBitmap source, result; | |
| 258 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); | |
| 259 result.setConfig(SkBitmap::kA8_Config, 300, 200); | |
| 260 | |
| 261 source.allocPixels(); | |
| 262 result.allocPixels(); | |
| 263 source.eraseRGB(50, 150, 200); | |
| 264 | |
| 265 // This computation should fail since all colors always vary together. | |
| 266 EXPECT_FALSE(color_utils::ComputePrincipalComponentImage(source, &result)); | |
| 267 } | |
| 268 | |
| 269 TEST(ColorUtils, ComputePrincipalComponentImage) { | |
| 270 gfx::Canvas canvas(gfx::Size(300, 200), ui::SCALE_FACTOR_100P, true); | |
| 271 | |
| 272 // The image consists of vertical non-overlapping stripes 100 pixels wide. | |
| 273 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10)); | |
| 274 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(100, 100, 100)); | |
| 275 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(255, 255, 255)); | |
| 276 SkBitmap source = | |
| 277 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | |
| 278 SkBitmap result; | |
| 279 result.setConfig(SkBitmap::kA8_Config, 300, 200); | |
| 280 result.allocPixels(); | |
| 281 | |
| 282 // This computation should fail since all colors always vary together. | |
| 283 EXPECT_TRUE(color_utils::ComputePrincipalComponentImage(source, &result)); | |
| 284 | |
| 285 uint8_t min_gl = 0; | |
| 286 uint8_t max_gl = 0; | |
| 287 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | |
| 288 | |
| 289 EXPECT_EQ(0, min_gl); | |
| 290 EXPECT_EQ(255, max_gl); | |
| 291 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); | |
| 292 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); | |
| 293 EXPECT_EQ(93U, SkColorGetA(result.getColor(150, 0))); | |
| 294 } | |
| OLD | NEW |