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_analysis.h" | 5 #include "ui/gfx/color_analysis.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "third_party/skia/include/core/SkBitmap.h" | 10 #include "third_party/skia/include/core/SkBitmap.h" |
11 #include "third_party/skia/include/core/SkColor.h" | 11 #include "third_party/skia/include/core/SkColor.h" |
12 #include "ui/gfx/canvas.h" | 12 #include "ui/gfx/canvas.h" |
13 #include "ui/gfx/rect.h" | 13 #include "ui/gfx/rect.h" |
14 | 14 |
15 using color_utils::FindClosestColor; | 15 namespace color_utils { |
16 | |
17 namespace { | |
18 | 16 |
19 const unsigned char k1x1White[] = { | 17 const unsigned char k1x1White[] = { |
20 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, | 18 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, |
21 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, | 19 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, |
22 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, | 20 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, |
23 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, | 21 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53, |
24 0xde, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, | 22 0xde, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, |
25 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, | 23 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, |
26 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, | 24 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, |
27 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, | 25 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, | 78 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, |
81 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, | 79 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57, |
82 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x14, 0x49, | 80 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x14, 0x49, |
83 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xcf, | 81 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xcf, |
84 0xc0, 0xc0, 0xc4, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, | 82 0xc0, 0xc0, 0xc4, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, |
85 0xf0, 0x1f, 0x00, 0x0c, 0x10, 0x02, 0x01, 0x2c, | 83 0xf0, 0x1f, 0x00, 0x0c, 0x10, 0x02, 0x01, 0x2c, |
86 0x8f, 0x8b, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x49, | 84 0x8f, 0x8b, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x49, |
87 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 | 85 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 |
88 }; | 86 }; |
89 | 87 |
90 class MockKMeanImageSampler : public color_utils::KMeanImageSampler { | 88 class MockKMeanImageSampler : public KMeanImageSampler { |
91 public: | 89 public: |
92 MockKMeanImageSampler() : current_result_index_(0) { | 90 MockKMeanImageSampler() : current_result_index_(0) { |
93 } | 91 } |
94 | 92 |
95 explicit MockKMeanImageSampler(const std::vector<int>& samples) | 93 explicit MockKMeanImageSampler(const std::vector<int>& samples) |
96 : prebaked_sample_results_(samples), | 94 : prebaked_sample_results_(samples), |
97 current_result_index_(0) { | 95 current_result_index_(0) { |
98 } | 96 } |
99 | 97 |
100 virtual ~MockKMeanImageSampler() { | 98 virtual ~MockKMeanImageSampler() { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 *max_gl = std::numeric_limits<uint8_t>::min(); | 138 *max_gl = std::numeric_limits<uint8_t>::min(); |
141 for (int y = 0; y < bitmap.height(); ++y) { | 139 for (int y = 0; y < bitmap.height(); ++y) { |
142 uint8_t* current_color = bitmap.getAddr8(0, y); | 140 uint8_t* current_color = bitmap.getAddr8(0, y); |
143 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { | 141 for (int x = 0; x < bitmap.width(); ++x, ++current_color) { |
144 *min_gl = std::min(*min_gl, *current_color); | 142 *min_gl = std::min(*min_gl, *current_color); |
145 *max_gl = std::max(*max_gl, *current_color); | 143 *max_gl = std::max(*max_gl, *current_color); |
146 } | 144 } |
147 } | 145 } |
148 } | 146 } |
149 | 147 |
150 } // namespace | |
151 | |
152 class ColorAnalysisTest : public testing::Test { | 148 class ColorAnalysisTest : public testing::Test { |
153 }; | 149 }; |
154 | 150 |
155 TEST_F(ColorAnalysisTest, CalculatePNGKMeanAllWhite) { | 151 TEST_F(ColorAnalysisTest, CalculatePNGKMeanAllWhite) { |
156 MockKMeanImageSampler test_sampler; | 152 MockKMeanImageSampler test_sampler; |
157 test_sampler.AddSample(0); | 153 test_sampler.AddSample(0); |
158 | 154 |
159 scoped_refptr<base::RefCountedBytes> png( | 155 scoped_refptr<base::RefCountedBytes> png( |
160 new base::RefCountedBytes( | 156 new base::RefCountedBytes( |
161 std::vector<unsigned char>( | 157 std::vector<unsigned char>( |
162 k1x1White, | 158 k1x1White, |
163 k1x1White + sizeof(k1x1White) / sizeof(unsigned char)))); | 159 k1x1White + sizeof(k1x1White) / sizeof(unsigned char)))); |
164 | 160 |
165 SkColor color = | 161 SkColor color = CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); |
166 color_utils::CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); | |
167 | 162 |
168 EXPECT_EQ(color, SK_ColorWHITE); | 163 EXPECT_EQ(color, SK_ColorWHITE); |
169 } | 164 } |
170 | 165 |
171 TEST_F(ColorAnalysisTest, CalculatePNGKMeanIgnoreWhite) { | 166 TEST_F(ColorAnalysisTest, CalculatePNGKMeanIgnoreWhite) { |
172 MockKMeanImageSampler test_sampler; | 167 MockKMeanImageSampler test_sampler; |
173 test_sampler.AddSample(0); | 168 test_sampler.AddSample(0); |
174 test_sampler.AddSample(1); | 169 test_sampler.AddSample(1); |
175 test_sampler.AddSample(2); | 170 test_sampler.AddSample(2); |
176 | 171 |
177 scoped_refptr<base::RefCountedBytes> png( | 172 scoped_refptr<base::RefCountedBytes> png( |
178 new base::RefCountedBytes( | 173 new base::RefCountedBytes( |
179 std::vector<unsigned char>( | 174 std::vector<unsigned char>( |
180 k1x3BlueWhite, | 175 k1x3BlueWhite, |
181 k1x3BlueWhite + sizeof(k1x3BlueWhite) / sizeof(unsigned char)))); | 176 k1x3BlueWhite + sizeof(k1x3BlueWhite) / sizeof(unsigned char)))); |
182 | 177 |
183 SkColor color = | 178 SkColor color = CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); |
184 color_utils::CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); | |
185 | 179 |
186 EXPECT_EQ(color, SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF)); | 180 EXPECT_EQ(color, SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF)); |
187 } | 181 } |
188 | 182 |
189 TEST_F(ColorAnalysisTest, CalculatePNGKMeanPickMostCommon) { | 183 TEST_F(ColorAnalysisTest, CalculatePNGKMeanPickMostCommon) { |
190 MockKMeanImageSampler test_sampler; | 184 MockKMeanImageSampler test_sampler; |
191 test_sampler.AddSample(0); | 185 test_sampler.AddSample(0); |
192 test_sampler.AddSample(1); | 186 test_sampler.AddSample(1); |
193 test_sampler.AddSample(2); | 187 test_sampler.AddSample(2); |
194 | 188 |
195 scoped_refptr<base::RefCountedBytes> png( | 189 scoped_refptr<base::RefCountedBytes> png( |
196 new base::RefCountedBytes( | 190 new base::RefCountedBytes( |
197 std::vector<unsigned char>( | 191 std::vector<unsigned char>( |
198 k1x3BlueRed, | 192 k1x3BlueRed, |
199 k1x3BlueRed + sizeof(k1x3BlueRed) / sizeof(unsigned char)))); | 193 k1x3BlueRed + sizeof(k1x3BlueRed) / sizeof(unsigned char)))); |
200 | 194 |
201 SkColor color = | 195 SkColor color = CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); |
202 color_utils::CalculateKMeanColorOfPNG(png, 100, 600, &test_sampler); | |
203 | 196 |
204 EXPECT_EQ(color, SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00)); | 197 EXPECT_EQ(color, SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00)); |
205 } | 198 } |
206 | 199 |
207 TEST_F(ColorAnalysisTest, GridSampler) { | 200 TEST_F(ColorAnalysisTest, GridSampler) { |
208 color_utils::GridSampler sampler; | 201 GridSampler sampler; |
209 const int kWidth = 16; | 202 const int kWidth = 16; |
210 const int kHeight = 16; | 203 const int kHeight = 16; |
211 // Sample starts at 1,1. | 204 // Sample starts at 1,1. |
212 EXPECT_EQ(1 + 1 * kWidth, sampler.GetSample(kWidth, kHeight)); | 205 EXPECT_EQ(1 + 1 * kWidth, sampler.GetSample(kWidth, kHeight)); |
213 EXPECT_EQ(1 + 4 * kWidth, sampler.GetSample(kWidth, kHeight)); | 206 EXPECT_EQ(1 + 4 * kWidth, sampler.GetSample(kWidth, kHeight)); |
214 EXPECT_EQ(1 + 7 * kWidth, sampler.GetSample(kWidth, kHeight)); | 207 EXPECT_EQ(1 + 7 * kWidth, sampler.GetSample(kWidth, kHeight)); |
215 EXPECT_EQ(1 + 10 * kWidth, sampler.GetSample(kWidth, kHeight)); | 208 EXPECT_EQ(1 + 10 * kWidth, sampler.GetSample(kWidth, kHeight)); |
216 // Step over by 3. | 209 // Step over by 3. |
217 EXPECT_EQ(4 + 1 * kWidth, sampler.GetSample(kWidth, kHeight)); | 210 EXPECT_EQ(4 + 1 * kWidth, sampler.GetSample(kWidth, kHeight)); |
218 EXPECT_EQ(4 + 4 * kWidth, sampler.GetSample(kWidth, kHeight)); | 211 EXPECT_EQ(4 + 4 * kWidth, sampler.GetSample(kWidth, kHeight)); |
(...skipping 28 matching lines...) Expand all Loading... |
247 EXPECT_EQ(SK_ColorBLACK, color); | 240 EXPECT_EQ(SK_ColorBLACK, color); |
248 } | 241 } |
249 | 242 |
250 TEST_F(ColorAnalysisTest, CalculateKMeanColorOfBitmap) { | 243 TEST_F(ColorAnalysisTest, CalculateKMeanColorOfBitmap) { |
251 // Create a 16x16 bitmap to represent a favicon. | 244 // Create a 16x16 bitmap to represent a favicon. |
252 SkBitmap bitmap; | 245 SkBitmap bitmap; |
253 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); | 246 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16); |
254 bitmap.allocPixels(); | 247 bitmap.allocPixels(); |
255 bitmap.eraseARGB(255, 100, 150, 200); | 248 bitmap.eraseARGB(255, 100, 150, 200); |
256 | 249 |
257 SkColor color = color_utils::CalculateKMeanColorOfBitmap(bitmap); | 250 SkColor color = CalculateKMeanColorOfBitmap(bitmap); |
258 EXPECT_EQ(255u, SkColorGetA(color)); | 251 EXPECT_EQ(255u, SkColorGetA(color)); |
259 // Color values are not exactly equal due to reversal of premultiplied alpha. | 252 // Color values are not exactly equal due to reversal of premultiplied alpha. |
260 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color))); | 253 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color))); |
261 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color))); | 254 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color))); |
262 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color))); | 255 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color))); |
263 | 256 |
264 // Test a bitmap with an alpha channel. | 257 // Test a bitmap with an alpha channel. |
265 bitmap.eraseARGB(128, 100, 150, 200); | 258 bitmap.eraseARGB(128, 100, 150, 200); |
266 color = color_utils::CalculateKMeanColorOfBitmap(bitmap); | 259 color = CalculateKMeanColorOfBitmap(bitmap); |
267 | 260 |
268 // Alpha channel should be ignored for dominant color calculation. | 261 // Alpha channel should be ignored for dominant color calculation. |
269 EXPECT_EQ(255u, SkColorGetA(color)); | 262 EXPECT_EQ(255u, SkColorGetA(color)); |
270 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color))); | 263 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color))); |
271 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color))); | 264 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color))); |
272 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color))); | 265 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color))); |
273 } | 266 } |
274 | 267 |
275 TEST_F(ColorAnalysisTest, ComputeColorCovarianceTrivial) { | 268 TEST_F(ColorAnalysisTest, ComputeColorCovarianceTrivial) { |
276 SkBitmap bitmap; | 269 SkBitmap bitmap; |
277 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 200); | 270 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 200); |
278 | 271 |
279 EXPECT_EQ(gfx::Matrix3F::Zeros(), | 272 EXPECT_EQ(gfx::Matrix3F::Zeros(), ComputeColorCovariance(bitmap)); |
280 color_utils::ComputeColorCovariance(bitmap)); | |
281 bitmap.allocPixels(); | 273 bitmap.allocPixels(); |
282 bitmap.eraseARGB(255, 50, 150, 200); | 274 bitmap.eraseARGB(255, 50, 150, 200); |
283 gfx::Matrix3F covariance = color_utils::ComputeColorCovariance(bitmap); | 275 gfx::Matrix3F covariance = ComputeColorCovariance(bitmap); |
284 // The answer should be all zeros. | 276 // The answer should be all zeros. |
285 EXPECT_TRUE(covariance == gfx::Matrix3F::Zeros()); | 277 EXPECT_TRUE(covariance == gfx::Matrix3F::Zeros()); |
286 } | 278 } |
287 | 279 |
288 TEST_F(ColorAnalysisTest, ComputeColorCovarianceWithCanvas) { | 280 TEST_F(ColorAnalysisTest, ComputeColorCovarianceWithCanvas) { |
289 gfx::Canvas canvas(gfx::Size(250, 200), 1.0f, true); | 281 gfx::Canvas canvas(gfx::Size(250, 200), 1.0f, true); |
290 // The image consists of vertical stripes, with color bands set to 100 | 282 // The image consists of vertical stripes, with color bands set to 100 |
291 // in overlapping stripes 150 pixels wide. | 283 // in overlapping stripes 150 pixels wide. |
292 canvas.FillRect(gfx::Rect(0, 0, 50, 200), SkColorSetRGB(100, 0, 0)); | 284 canvas.FillRect(gfx::Rect(0, 0, 50, 200), SkColorSetRGB(100, 0, 0)); |
293 canvas.FillRect(gfx::Rect(50, 0, 50, 200), SkColorSetRGB(100, 100, 0)); | 285 canvas.FillRect(gfx::Rect(50, 0, 50, 200), SkColorSetRGB(100, 100, 0)); |
294 canvas.FillRect(gfx::Rect(100, 0, 50, 200), SkColorSetRGB(100, 100, 100)); | 286 canvas.FillRect(gfx::Rect(100, 0, 50, 200), SkColorSetRGB(100, 100, 100)); |
295 canvas.FillRect(gfx::Rect(150, 0, 50, 200), SkColorSetRGB(0, 100, 100)); | 287 canvas.FillRect(gfx::Rect(150, 0, 50, 200), SkColorSetRGB(0, 100, 100)); |
296 canvas.FillRect(gfx::Rect(200, 0, 50, 200), SkColorSetRGB(0, 0, 100)); | 288 canvas.FillRect(gfx::Rect(200, 0, 50, 200), SkColorSetRGB(0, 0, 100)); |
297 | 289 |
298 SkBitmap bitmap = | 290 SkBitmap bitmap = |
299 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | 291 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); |
300 gfx::Matrix3F covariance = color_utils::ComputeColorCovariance(bitmap); | 292 gfx::Matrix3F covariance = ComputeColorCovariance(bitmap); |
301 | 293 |
302 gfx::Matrix3F expected_covariance = gfx::Matrix3F::Zeros(); | 294 gfx::Matrix3F expected_covariance = gfx::Matrix3F::Zeros(); |
303 expected_covariance.set(2400, 400, -1600, | 295 expected_covariance.set(2400, 400, -1600, |
304 400, 2400, 400, | 296 400, 2400, 400, |
305 -1600, 400, 2400); | 297 -1600, 400, 2400); |
306 EXPECT_EQ(expected_covariance, covariance); | 298 EXPECT_EQ(expected_covariance, covariance); |
307 } | 299 } |
308 | 300 |
309 TEST_F(ColorAnalysisTest, ApplyColorReductionSingleColor) { | 301 TEST_F(ColorAnalysisTest, ApplyColorReductionSingleColor) { |
310 // The test runs color reduction on a single-colot image, where results are | 302 // The test runs color reduction on a single-colot image, where results are |
311 // bound to be uninteresting. This is an important edge case, though. | 303 // bound to be uninteresting. This is an important edge case, though. |
312 SkBitmap source, result; | 304 SkBitmap source, result; |
313 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); | 305 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); |
314 result.setConfig(SkBitmap::kA8_Config, 300, 200); | 306 result.setConfig(SkBitmap::kA8_Config, 300, 200); |
315 | 307 |
316 source.allocPixels(); | 308 source.allocPixels(); |
317 result.allocPixels(); | 309 result.allocPixels(); |
318 source.eraseARGB(255, 50, 150, 200); | 310 source.eraseARGB(255, 50, 150, 200); |
319 | 311 |
320 gfx::Vector3dF transform(1.0f, .5f, 0.1f); | 312 gfx::Vector3dF transform(1.0f, .5f, 0.1f); |
321 // This transform, if not scaled, should result in GL=145. | 313 // This transform, if not scaled, should result in GL=145. |
322 EXPECT_TRUE(color_utils::ApplyColorReduction( | 314 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result)); |
323 source, transform, false, &result)); | |
324 | 315 |
325 uint8_t min_gl = 0; | 316 uint8_t min_gl = 0; |
326 uint8_t max_gl = 0; | 317 uint8_t max_gl = 0; |
327 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 318 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
328 EXPECT_EQ(145, min_gl); | 319 EXPECT_EQ(145, min_gl); |
329 EXPECT_EQ(145, max_gl); | 320 EXPECT_EQ(145, max_gl); |
330 | 321 |
331 // Now scan requesting rescale. Expect all 0. | 322 // Now scan requesting rescale. Expect all 0. |
332 EXPECT_TRUE(color_utils::ApplyColorReduction( | 323 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result)); |
333 source, transform, true, &result)); | |
334 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 324 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
335 EXPECT_EQ(0, min_gl); | 325 EXPECT_EQ(0, min_gl); |
336 EXPECT_EQ(0, max_gl); | 326 EXPECT_EQ(0, max_gl); |
337 | 327 |
338 // Test cliping to upper limit. | 328 // Test cliping to upper limit. |
339 transform.set_z(1.1f); | 329 transform.set_z(1.1f); |
340 EXPECT_TRUE(color_utils::ApplyColorReduction( | 330 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result)); |
341 source, transform, false, &result)); | |
342 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 331 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
343 EXPECT_EQ(0xFF, min_gl); | 332 EXPECT_EQ(0xFF, min_gl); |
344 EXPECT_EQ(0xFF, max_gl); | 333 EXPECT_EQ(0xFF, max_gl); |
345 | 334 |
346 // Test cliping to upper limit. | 335 // Test cliping to upper limit. |
347 transform.Scale(-1.0f); | 336 transform.Scale(-1.0f); |
348 EXPECT_TRUE(color_utils::ApplyColorReduction( | 337 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result)); |
349 source, transform, false, &result)); | |
350 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 338 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
351 EXPECT_EQ(0x0, min_gl); | 339 EXPECT_EQ(0x0, min_gl); |
352 EXPECT_EQ(0x0, max_gl); | 340 EXPECT_EQ(0x0, max_gl); |
353 } | 341 } |
354 | 342 |
355 TEST_F(ColorAnalysisTest, ApplyColorReductionBlackAndWhite) { | 343 TEST_F(ColorAnalysisTest, ApplyColorReductionBlackAndWhite) { |
356 // Check with images with multiple colors. This is really different only when | 344 // Check with images with multiple colors. This is really different only when |
357 // the result is scaled. | 345 // the result is scaled. |
358 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); | 346 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); |
359 | 347 |
360 // The image consists of vertical non-overlapping stripes 150 pixels wide. | 348 // The image consists of vertical non-overlapping stripes 150 pixels wide. |
361 canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0)); | 349 canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0)); |
362 canvas.FillRect(gfx::Rect(150, 0, 150, 200), SkColorSetRGB(255, 255, 255)); | 350 canvas.FillRect(gfx::Rect(150, 0, 150, 200), SkColorSetRGB(255, 255, 255)); |
363 SkBitmap source = | 351 SkBitmap source = |
364 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | 352 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); |
365 SkBitmap result; | 353 SkBitmap result; |
366 result.setConfig(SkBitmap::kA8_Config, 300, 200); | 354 result.setConfig(SkBitmap::kA8_Config, 300, 200); |
367 result.allocPixels(); | 355 result.allocPixels(); |
368 | 356 |
369 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); | 357 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); |
370 EXPECT_TRUE(color_utils::ApplyColorReduction( | 358 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result)); |
371 source, transform, true, &result)); | |
372 uint8_t min_gl = 0; | 359 uint8_t min_gl = 0; |
373 uint8_t max_gl = 0; | 360 uint8_t max_gl = 0; |
374 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 361 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
375 | 362 |
376 EXPECT_EQ(0, min_gl); | 363 EXPECT_EQ(0, min_gl); |
377 EXPECT_EQ(255, max_gl); | 364 EXPECT_EQ(255, max_gl); |
378 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); | 365 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); |
379 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); | 366 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); |
380 | 367 |
381 // Reverse test. | 368 // Reverse test. |
382 transform.Scale(-1.0f); | 369 transform.Scale(-1.0f); |
383 EXPECT_TRUE(color_utils::ApplyColorReduction( | 370 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result)); |
384 source, transform, true, &result)); | |
385 min_gl = 0; | 371 min_gl = 0; |
386 max_gl = 0; | 372 max_gl = 0; |
387 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 373 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
388 | 374 |
389 EXPECT_EQ(0, min_gl); | 375 EXPECT_EQ(0, min_gl); |
390 EXPECT_EQ(255, max_gl); | 376 EXPECT_EQ(255, max_gl); |
391 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(0, 0))); | 377 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(0, 0))); |
392 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | 378 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); |
393 } | 379 } |
394 | 380 |
395 TEST_F(ColorAnalysisTest, ApplyColorReductionMultiColor) { | 381 TEST_F(ColorAnalysisTest, ApplyColorReductionMultiColor) { |
396 // Check with images with multiple colors. This is really different only when | 382 // Check with images with multiple colors. This is really different only when |
397 // the result is scaled. | 383 // the result is scaled. |
398 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); | 384 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); |
399 | 385 |
400 // The image consists of vertical non-overlapping stripes 100 pixels wide. | 386 // The image consists of vertical non-overlapping stripes 100 pixels wide. |
401 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0)); | 387 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0)); |
402 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(0, 255, 0)); | 388 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(0, 255, 0)); |
403 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(0, 0, 128)); | 389 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(0, 0, 128)); |
404 SkBitmap source = | 390 SkBitmap source = |
405 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | 391 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); |
406 SkBitmap result; | 392 SkBitmap result; |
407 result.setConfig(SkBitmap::kA8_Config, 300, 200); | 393 result.setConfig(SkBitmap::kA8_Config, 300, 200); |
408 result.allocPixels(); | 394 result.allocPixels(); |
409 | 395 |
410 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); | 396 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f); |
411 EXPECT_TRUE(color_utils::ApplyColorReduction( | 397 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result)); |
412 source, transform, false, &result)); | |
413 uint8_t min_gl = 0; | 398 uint8_t min_gl = 0; |
414 uint8_t max_gl = 0; | 399 uint8_t max_gl = 0; |
415 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 400 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
416 EXPECT_EQ(12, min_gl); | 401 EXPECT_EQ(12, min_gl); |
417 EXPECT_EQ(127, max_gl); | 402 EXPECT_EQ(127, max_gl); |
418 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | 403 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); |
419 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); | 404 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); |
420 EXPECT_EQ(100U, SkColorGetA(result.getColor(0, 0))); | 405 EXPECT_EQ(100U, SkColorGetA(result.getColor(0, 0))); |
421 | 406 |
422 EXPECT_TRUE(color_utils::ApplyColorReduction( | 407 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result)); |
423 source, transform, true, &result)); | |
424 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 408 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
425 EXPECT_EQ(0, min_gl); | 409 EXPECT_EQ(0, min_gl); |
426 EXPECT_EQ(255, max_gl); | 410 EXPECT_EQ(255, max_gl); |
427 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); | 411 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199))); |
428 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); | 412 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0))); |
429 EXPECT_EQ(193U, SkColorGetA(result.getColor(0, 0))); | 413 EXPECT_EQ(193U, SkColorGetA(result.getColor(0, 0))); |
430 } | 414 } |
431 | 415 |
432 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImageNotComputable) { | 416 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImageNotComputable) { |
433 SkBitmap source, result; | 417 SkBitmap source, result; |
434 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); | 418 source.setConfig(SkBitmap::kARGB_8888_Config, 300, 200); |
435 result.setConfig(SkBitmap::kA8_Config, 300, 200); | 419 result.setConfig(SkBitmap::kA8_Config, 300, 200); |
436 | 420 |
437 source.allocPixels(); | 421 source.allocPixels(); |
438 result.allocPixels(); | 422 result.allocPixels(); |
439 source.eraseARGB(255, 50, 150, 200); | 423 source.eraseARGB(255, 50, 150, 200); |
440 | 424 |
441 // This computation should fail since all colors always vary together. | 425 // This computation should fail since all colors always vary together. |
442 EXPECT_FALSE(color_utils::ComputePrincipalComponentImage(source, &result)); | 426 EXPECT_FALSE(ComputePrincipalComponentImage(source, &result)); |
443 } | 427 } |
444 | 428 |
445 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImage) { | 429 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImage) { |
446 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); | 430 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true); |
447 | 431 |
448 // The image consists of vertical non-overlapping stripes 100 pixels wide. | 432 // The image consists of vertical non-overlapping stripes 100 pixels wide. |
449 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10)); | 433 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10)); |
450 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(100, 100, 100)); | 434 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(100, 100, 100)); |
451 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(255, 255, 255)); | 435 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(255, 255, 255)); |
452 SkBitmap source = | 436 SkBitmap source = |
453 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); | 437 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false); |
454 SkBitmap result; | 438 SkBitmap result; |
455 result.setConfig(SkBitmap::kA8_Config, 300, 200); | 439 result.setConfig(SkBitmap::kA8_Config, 300, 200); |
456 result.allocPixels(); | 440 result.allocPixels(); |
457 | 441 |
458 // This computation should fail since all colors always vary together. | 442 // This computation should fail since all colors always vary together. |
459 EXPECT_TRUE(color_utils::ComputePrincipalComponentImage(source, &result)); | 443 EXPECT_TRUE(ComputePrincipalComponentImage(source, &result)); |
460 | 444 |
461 uint8_t min_gl = 0; | 445 uint8_t min_gl = 0; |
462 uint8_t max_gl = 0; | 446 uint8_t max_gl = 0; |
463 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); | 447 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl); |
464 | 448 |
465 EXPECT_EQ(0, min_gl); | 449 EXPECT_EQ(0, min_gl); |
466 EXPECT_EQ(255, max_gl); | 450 EXPECT_EQ(255, max_gl); |
467 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); | 451 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0))); |
468 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); | 452 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199))); |
469 EXPECT_EQ(93U, SkColorGetA(result.getColor(150, 0))); | 453 EXPECT_EQ(93U, SkColorGetA(result.getColor(150, 0))); |
470 } | 454 } |
| 455 |
| 456 } // namespace color_utils |
OLD | NEW |