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 // Compute minimal and maximal graylevel (or alphalevel) of the input |bitmap|. | |
20 // |bitmap| has to be allocated and configured to kA8_Config. | |
21 void Calculate8bitBitmapMinMax(const SkBitmap& bitmap, | |
22 uint8_t* min_gl, | |
23 uint8_t* max_gl) { | |
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 | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: Remove blank line.
motek.
2013/02/22 15:42:56
Done.
| |
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 | |
Alexei Svitkine (slow)
2013/02/22 02:24:06
Nit: Remove blank line.
motek.
2013/02/22 15:42:56
Done.
| |
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 |