mojo: Fix map of booleans for python bindings.
[chromium-blink-merge.git] / ui / gfx / color_analysis_unittest.cc
blob128209afe204937b547df76c57fc0b81e560d5ec
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
3 // found in the LICENSE file.
5 #include "ui/gfx/color_analysis.h"
7 #include <vector>
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/skia/include/core/SkBitmap.h"
11 #include "third_party/skia/include/core/SkColor.h"
12 #include "ui/gfx/canvas.h"
13 #include "ui/gfx/color_utils.h"
14 #include "ui/gfx/image/image.h"
15 #include "ui/gfx/rect.h"
17 namespace color_utils {
19 const unsigned char k1x1White[] = {
20 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
21 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
22 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
23 0x08, 0x02, 0x00, 0x00, 0x00, 0x90, 0x77, 0x53,
24 0xde, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
25 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
26 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
27 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00,
28 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74,
29 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x02, 0x11, 0x15,
30 0x16, 0x1b, 0xaa, 0x58, 0x38, 0x76, 0x00, 0x00,
31 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f,
32 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72,
33 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69,
34 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57,
35 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x0c, 0x49,
36 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff,
37 0xff, 0x3f, 0x00, 0x05, 0xfe, 0x02, 0xfe, 0xdc,
38 0xcc, 0x59, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x49,
39 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
42 const unsigned char k1x3BlueWhite[] = {
43 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
44 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
45 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
46 0x08, 0x02, 0x00, 0x00, 0x00, 0xdd, 0xbf, 0xf2,
47 0xd5, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
48 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
49 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
50 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00,
51 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74,
52 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x02, 0x12, 0x01,
53 0x0a, 0x2c, 0xfd, 0x08, 0x64, 0x66, 0x00, 0x00,
54 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f,
55 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72,
56 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69,
57 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57,
58 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x14, 0x49,
59 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff,
60 0xff, 0x3f, 0x13, 0x03, 0x03, 0x03, 0x03, 0x03,
61 0xc3, 0x7f, 0x00, 0x1e, 0xfd, 0x03, 0xff, 0xde,
62 0x72, 0x58, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x49,
63 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
66 const unsigned char k1x3BlueRed[] = {
67 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
68 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52,
69 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03,
70 0x08, 0x02, 0x00, 0x00, 0x00, 0xdd, 0xbf, 0xf2,
71 0xd5, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47,
72 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
73 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
74 0x0b, 0x13, 0x00, 0x00, 0x0b, 0x13, 0x01, 0x00,
75 0x9a, 0x9c, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74,
76 0x49, 0x4d, 0x45, 0x07, 0xdb, 0x02, 0x12, 0x01,
77 0x07, 0x09, 0x03, 0xa2, 0xce, 0x6c, 0x00, 0x00,
78 0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x43, 0x6f,
79 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x43, 0x72,
80 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69,
81 0x74, 0x68, 0x20, 0x47, 0x49, 0x4d, 0x50, 0x57,
82 0x81, 0x0e, 0x17, 0x00, 0x00, 0x00, 0x14, 0x49,
83 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xcf,
84 0xc0, 0xc0, 0xc4, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
85 0xf0, 0x1f, 0x00, 0x0c, 0x10, 0x02, 0x01, 0x2c,
86 0x8f, 0x8b, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x49,
87 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
90 const HSL kDefaultLowerBound = {-1, -1, 0.15};
91 const HSL kDefaultUpperBound = {-1, -1, 0.85};
93 // Creates a 1-dimensional png of the pixel colors found in |colors|.
94 scoped_refptr<base::RefCountedMemory> CreateTestPNG(
95 const std::vector<SkColor>& colors) {
96 SkBitmap bitmap;
97 bitmap.allocN32Pixels(colors.size(), 1);
99 SkAutoLockPixels lock(bitmap);
100 for (size_t i = 0; i < colors.size(); ++i) {
101 bitmap.eraseArea(SkIRect::MakeXYWH(i, 0, 1, 1), colors[i]);
103 return gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes();
106 class MockKMeanImageSampler : public KMeanImageSampler {
107 public:
108 MockKMeanImageSampler() : current_result_index_(0) {
111 explicit MockKMeanImageSampler(const std::vector<int>& samples)
112 : prebaked_sample_results_(samples),
113 current_result_index_(0) {
116 virtual ~MockKMeanImageSampler() {
119 void AddSample(int sample) {
120 prebaked_sample_results_.push_back(sample);
123 virtual int GetSample(int width, int height) override {
124 if (current_result_index_ >= prebaked_sample_results_.size()) {
125 current_result_index_ = 0;
128 if (prebaked_sample_results_.empty()) {
129 return 0;
132 return prebaked_sample_results_[current_result_index_++];
135 protected:
136 std::vector<int> prebaked_sample_results_;
137 size_t current_result_index_;
140 // Return true if a color channel is approximately equal to an expected value.
141 bool ChannelApproximatelyEqual(int expected, uint8_t channel) {
142 return (abs(expected - static_cast<int>(channel)) <= 1);
145 // Compute minimal and maximal graylevel (or alphalevel) of the input |bitmap|.
146 // |bitmap| has to be allocated and configured to kA8_Config.
147 void Calculate8bitBitmapMinMax(const SkBitmap& bitmap,
148 uint8_t* min_gl,
149 uint8_t* max_gl) {
150 SkAutoLockPixels bitmap_lock(bitmap);
151 DCHECK(bitmap.getPixels());
152 DCHECK_EQ(bitmap.colorType(), kAlpha_8_SkColorType);
153 DCHECK(min_gl);
154 DCHECK(max_gl);
155 *min_gl = std::numeric_limits<uint8_t>::max();
156 *max_gl = std::numeric_limits<uint8_t>::min();
157 for (int y = 0; y < bitmap.height(); ++y) {
158 uint8_t* current_color = bitmap.getAddr8(0, y);
159 for (int x = 0; x < bitmap.width(); ++x, ++current_color) {
160 *min_gl = std::min(*min_gl, *current_color);
161 *max_gl = std::max(*max_gl, *current_color);
166 class ColorAnalysisTest : public testing::Test {
169 TEST_F(ColorAnalysisTest, CalculatePNGKMeanAllWhite) {
170 MockKMeanImageSampler test_sampler;
171 test_sampler.AddSample(0);
173 scoped_refptr<base::RefCountedBytes> png(
174 new base::RefCountedBytes(
175 std::vector<unsigned char>(
176 k1x1White,
177 k1x1White + sizeof(k1x1White) / sizeof(unsigned char))));
179 SkColor color = CalculateKMeanColorOfPNG(
180 png, kDefaultLowerBound, kDefaultUpperBound, &test_sampler);
182 EXPECT_EQ(color, SK_ColorWHITE);
185 TEST_F(ColorAnalysisTest, CalculatePNGKMeanIgnoreWhiteLightness) {
186 MockKMeanImageSampler test_sampler;
187 test_sampler.AddSample(0);
188 test_sampler.AddSample(1);
189 test_sampler.AddSample(2);
191 scoped_refptr<base::RefCountedBytes> png(
192 new base::RefCountedBytes(
193 std::vector<unsigned char>(
194 k1x3BlueWhite,
195 k1x3BlueWhite + sizeof(k1x3BlueWhite) / sizeof(unsigned char))));
197 SkColor color = CalculateKMeanColorOfPNG(
198 png, kDefaultLowerBound, kDefaultUpperBound, &test_sampler);
200 EXPECT_EQ(SkColorSetARGB(0xFF, 0x00, 0x00, 0xFF), color);
203 TEST_F(ColorAnalysisTest, CalculatePNGKMeanPickMostCommon) {
204 MockKMeanImageSampler test_sampler;
205 test_sampler.AddSample(0);
206 test_sampler.AddSample(1);
207 test_sampler.AddSample(2);
209 scoped_refptr<base::RefCountedBytes> png(
210 new base::RefCountedBytes(
211 std::vector<unsigned char>(
212 k1x3BlueRed,
213 k1x3BlueRed + sizeof(k1x3BlueRed) / sizeof(unsigned char))));
215 SkColor color = CalculateKMeanColorOfPNG(
216 png, kDefaultLowerBound, kDefaultUpperBound, &test_sampler);
218 EXPECT_EQ(SkColorSetARGB(0xFF, 0xFF, 0x00, 0x00), color);
221 TEST_F(ColorAnalysisTest, CalculatePNGKMeanIgnoreRedHue) {
222 MockKMeanImageSampler test_sampler;
223 test_sampler.AddSample(0);
224 test_sampler.AddSample(1);
225 test_sampler.AddSample(2);
227 std::vector<SkColor> colors(4, SK_ColorRED);
228 colors[1] = SK_ColorBLUE;
230 scoped_refptr<base::RefCountedMemory> png = CreateTestPNG(colors);
232 HSL lower = {0.2, -1, 0.15};
233 HSL upper = {0.8, -1, 0.85};
234 SkColor color = CalculateKMeanColorOfPNG(
235 png, lower, upper, &test_sampler);
237 EXPECT_EQ(SK_ColorBLUE, color);
240 TEST_F(ColorAnalysisTest, CalculatePNGKMeanIgnoreGreySaturation) {
241 MockKMeanImageSampler test_sampler;
242 test_sampler.AddSample(0);
243 test_sampler.AddSample(1);
244 test_sampler.AddSample(2);
246 std::vector<SkColor> colors(4, SK_ColorGRAY);
247 colors[1] = SK_ColorBLUE;
249 scoped_refptr<base::RefCountedMemory> png = CreateTestPNG(colors);
250 HSL lower = {-1, 0.3, -1};
251 HSL upper = {-1, 1, -1};
252 SkColor color = CalculateKMeanColorOfPNG(
253 png, lower, upper, &test_sampler);
255 EXPECT_EQ(SK_ColorBLUE, color);
258 TEST_F(ColorAnalysisTest, GridSampler) {
259 GridSampler sampler;
260 const int kWidth = 16;
261 const int kHeight = 16;
262 // Sample starts at 1,1.
263 EXPECT_EQ(1 + 1 * kWidth, sampler.GetSample(kWidth, kHeight));
264 EXPECT_EQ(1 + 4 * kWidth, sampler.GetSample(kWidth, kHeight));
265 EXPECT_EQ(1 + 7 * kWidth, sampler.GetSample(kWidth, kHeight));
266 EXPECT_EQ(1 + 10 * kWidth, sampler.GetSample(kWidth, kHeight));
267 // Step over by 3.
268 EXPECT_EQ(4 + 1 * kWidth, sampler.GetSample(kWidth, kHeight));
269 EXPECT_EQ(4 + 4 * kWidth, sampler.GetSample(kWidth, kHeight));
270 EXPECT_EQ(4 + 7 * kWidth, sampler.GetSample(kWidth, kHeight));
271 EXPECT_EQ(4 + 10 * kWidth, sampler.GetSample(kWidth, kHeight));
274 TEST_F(ColorAnalysisTest, FindClosestColor) {
275 // Empty image returns input color.
276 SkColor color = FindClosestColor(NULL, 0, 0, SK_ColorRED);
277 EXPECT_EQ(SK_ColorRED, color);
279 // Single color image returns that color.
280 SkBitmap bitmap;
281 bitmap.allocN32Pixels(16, 16);
282 bitmap.eraseColor(SK_ColorWHITE);
283 color = FindClosestColor(static_cast<uint8_t*>(bitmap.getPixels()),
284 bitmap.width(),
285 bitmap.height(),
286 SK_ColorRED);
287 EXPECT_EQ(SK_ColorWHITE, color);
289 // Write a black pixel into the image. A dark grey input pixel should match
290 // the black one in the image.
291 uint32_t* pixel = bitmap.getAddr32(0, 0);
292 *pixel = SK_ColorBLACK;
293 color = FindClosestColor(static_cast<uint8_t*>(bitmap.getPixels()),
294 bitmap.width(),
295 bitmap.height(),
296 SK_ColorDKGRAY);
297 EXPECT_EQ(SK_ColorBLACK, color);
300 TEST_F(ColorAnalysisTest, CalculateKMeanColorOfBitmap) {
301 // Create a 16x16 bitmap to represent a favicon.
302 SkBitmap bitmap;
303 bitmap.allocN32Pixels(16, 16);
304 bitmap.eraseARGB(255, 100, 150, 200);
306 SkColor color = CalculateKMeanColorOfBitmap(bitmap);
307 EXPECT_EQ(255u, SkColorGetA(color));
308 // Color values are not exactly equal due to reversal of premultiplied alpha.
309 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color)));
310 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color)));
311 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color)));
313 // Test a bitmap with an alpha channel.
314 bitmap.eraseARGB(128, 100, 150, 200);
315 color = CalculateKMeanColorOfBitmap(bitmap);
317 // Alpha channel should be ignored for dominant color calculation.
318 EXPECT_EQ(255u, SkColorGetA(color));
319 EXPECT_TRUE(ChannelApproximatelyEqual(100, SkColorGetR(color)));
320 EXPECT_TRUE(ChannelApproximatelyEqual(150, SkColorGetG(color)));
321 EXPECT_TRUE(ChannelApproximatelyEqual(200, SkColorGetB(color)));
324 TEST_F(ColorAnalysisTest, ComputeColorCovarianceTrivial) {
325 SkBitmap bitmap;
326 bitmap.setInfo(SkImageInfo::MakeN32Premul(100, 200));
328 EXPECT_EQ(gfx::Matrix3F::Zeros(), ComputeColorCovariance(bitmap));
329 bitmap.allocPixels();
330 bitmap.eraseARGB(255, 50, 150, 200);
331 gfx::Matrix3F covariance = ComputeColorCovariance(bitmap);
332 // The answer should be all zeros.
333 EXPECT_TRUE(covariance == gfx::Matrix3F::Zeros());
336 TEST_F(ColorAnalysisTest, ComputeColorCovarianceWithCanvas) {
337 gfx::Canvas canvas(gfx::Size(250, 200), 1.0f, true);
338 // The image consists of vertical stripes, with color bands set to 100
339 // in overlapping stripes 150 pixels wide.
340 canvas.FillRect(gfx::Rect(0, 0, 50, 200), SkColorSetRGB(100, 0, 0));
341 canvas.FillRect(gfx::Rect(50, 0, 50, 200), SkColorSetRGB(100, 100, 0));
342 canvas.FillRect(gfx::Rect(100, 0, 50, 200), SkColorSetRGB(100, 100, 100));
343 canvas.FillRect(gfx::Rect(150, 0, 50, 200), SkColorSetRGB(0, 100, 100));
344 canvas.FillRect(gfx::Rect(200, 0, 50, 200), SkColorSetRGB(0, 0, 100));
346 SkBitmap bitmap =
347 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
348 gfx::Matrix3F covariance = ComputeColorCovariance(bitmap);
350 gfx::Matrix3F expected_covariance = gfx::Matrix3F::Zeros();
351 expected_covariance.set(2400, 400, -1600,
352 400, 2400, 400,
353 -1600, 400, 2400);
354 EXPECT_EQ(expected_covariance, covariance);
357 TEST_F(ColorAnalysisTest, ApplyColorReductionSingleColor) {
358 // The test runs color reduction on a single-colot image, where results are
359 // bound to be uninteresting. This is an important edge case, though.
360 SkBitmap source, result;
361 source.allocN32Pixels(300, 200);
362 result.allocPixels(SkImageInfo::MakeA8(300, 200));
364 source.eraseARGB(255, 50, 150, 200);
366 gfx::Vector3dF transform(1.0f, .5f, 0.1f);
367 // This transform, if not scaled, should result in GL=145.
368 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result));
370 uint8_t min_gl = 0;
371 uint8_t max_gl = 0;
372 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
373 EXPECT_EQ(145, min_gl);
374 EXPECT_EQ(145, max_gl);
376 // Now scan requesting rescale. Expect all 0.
377 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result));
378 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
379 EXPECT_EQ(0, min_gl);
380 EXPECT_EQ(0, max_gl);
382 // Test cliping to upper limit.
383 transform.set_z(1.1f);
384 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result));
385 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
386 EXPECT_EQ(0xFF, min_gl);
387 EXPECT_EQ(0xFF, max_gl);
389 // Test cliping to upper limit.
390 transform.Scale(-1.0f);
391 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result));
392 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
393 EXPECT_EQ(0x0, min_gl);
394 EXPECT_EQ(0x0, max_gl);
397 TEST_F(ColorAnalysisTest, ApplyColorReductionBlackAndWhite) {
398 // Check with images with multiple colors. This is really different only when
399 // the result is scaled.
400 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
402 // The image consists of vertical non-overlapping stripes 150 pixels wide.
403 canvas.FillRect(gfx::Rect(0, 0, 150, 200), SkColorSetRGB(0, 0, 0));
404 canvas.FillRect(gfx::Rect(150, 0, 150, 200), SkColorSetRGB(255, 255, 255));
405 SkBitmap source =
406 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
407 SkBitmap result;
408 result.allocPixels(SkImageInfo::MakeA8(300, 200));
410 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f);
411 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result));
412 uint8_t min_gl = 0;
413 uint8_t max_gl = 0;
414 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
416 EXPECT_EQ(0, min_gl);
417 EXPECT_EQ(255, max_gl);
418 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0)));
419 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199)));
421 // Reverse test.
422 transform.Scale(-1.0f);
423 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result));
424 min_gl = 0;
425 max_gl = 0;
426 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
428 EXPECT_EQ(0, min_gl);
429 EXPECT_EQ(255, max_gl);
430 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(0, 0)));
431 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199)));
434 TEST_F(ColorAnalysisTest, ApplyColorReductionMultiColor) {
435 // Check with images with multiple colors. This is really different only when
436 // the result is scaled.
437 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
439 // The image consists of vertical non-overlapping stripes 100 pixels wide.
440 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(100, 0, 0));
441 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(0, 255, 0));
442 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(0, 0, 128));
443 SkBitmap source =
444 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
445 SkBitmap result;
446 result.allocPixels(SkImageInfo::MakeA8(300, 200));
448 gfx::Vector3dF transform(1.0f, 0.5f, 0.1f);
449 EXPECT_TRUE(ApplyColorReduction(source, transform, false, &result));
450 uint8_t min_gl = 0;
451 uint8_t max_gl = 0;
452 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
453 EXPECT_EQ(12, min_gl);
454 EXPECT_EQ(127, max_gl);
455 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199)));
456 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0)));
457 EXPECT_EQ(100U, SkColorGetA(result.getColor(0, 0)));
459 EXPECT_TRUE(ApplyColorReduction(source, transform, true, &result));
460 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
461 EXPECT_EQ(0, min_gl);
462 EXPECT_EQ(255, max_gl);
463 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(299, 199)));
464 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(150, 0)));
465 EXPECT_EQ(193U, SkColorGetA(result.getColor(0, 0)));
468 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImageNotComputable) {
469 SkBitmap source, result;
470 source.allocN32Pixels(300, 200);
471 result.allocPixels(SkImageInfo::MakeA8(300, 200));
473 source.eraseARGB(255, 50, 150, 200);
475 // This computation should fail since all colors always vary together.
476 EXPECT_FALSE(ComputePrincipalComponentImage(source, &result));
479 TEST_F(ColorAnalysisTest, ComputePrincipalComponentImage) {
480 gfx::Canvas canvas(gfx::Size(300, 200), 1.0f, true);
482 // The image consists of vertical non-overlapping stripes 100 pixels wide.
483 canvas.FillRect(gfx::Rect(0, 0, 100, 200), SkColorSetRGB(10, 10, 10));
484 canvas.FillRect(gfx::Rect(100, 0, 100, 200), SkColorSetRGB(100, 100, 100));
485 canvas.FillRect(gfx::Rect(200, 0, 100, 200), SkColorSetRGB(255, 255, 255));
486 SkBitmap source =
487 skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(false);
488 SkBitmap result;
489 result.allocPixels(SkImageInfo::MakeA8(300, 200));
491 // This computation should fail since all colors always vary together.
492 EXPECT_TRUE(ComputePrincipalComponentImage(source, &result));
494 uint8_t min_gl = 0;
495 uint8_t max_gl = 0;
496 Calculate8bitBitmapMinMax(result, &min_gl, &max_gl);
498 EXPECT_EQ(0, min_gl);
499 EXPECT_EQ(255, max_gl);
500 EXPECT_EQ(min_gl, SkColorGetA(result.getColor(0, 0)));
501 EXPECT_EQ(max_gl, SkColorGetA(result.getColor(299, 199)));
502 EXPECT_EQ(93U, SkColorGetA(result.getColor(150, 0)));
505 } // namespace color_utils