- add sources.
[platform/framework/web/crosswalk.git] / src / cc / test / pixel_comparator.cc
1 // Copyright (c) 2013 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.
4
5 #include "cc/test/pixel_comparator.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10
11 namespace cc {
12
13 ExactPixelComparator::ExactPixelComparator(const bool discard_alpha)
14     : discard_alpha_(discard_alpha) {
15 }
16
17 bool ExactPixelComparator::Compare(const SkBitmap& actual_bmp,
18                                    const SkBitmap& expected_bmp) const {
19   // Number of pixels with an error
20   int error_pixels_count = 0;
21
22   // Check that bitmaps have identical dimensions.
23   DCHECK(actual_bmp.width() == expected_bmp.width() &&
24          actual_bmp.height() == expected_bmp.height());
25
26   SkAutoLockPixels lock_actual_bmp(actual_bmp);
27   SkAutoLockPixels lock_expected_bmp(expected_bmp);
28
29   for (int x = 0; x < actual_bmp.width(); ++x) {
30     for (int y = 0; y < actual_bmp.height(); ++y) {
31       SkColor actual_color = actual_bmp.getColor(x, y);
32       SkColor expected_color = expected_bmp.getColor(x, y);
33       if (discard_alpha_) {
34         actual_color = SkColorSetA(actual_color, 0);
35         expected_color = SkColorSetA(expected_color, 0);
36       }
37
38       if (actual_color != expected_color) {
39         ++error_pixels_count;
40         LOG(ERROR) << "Pixel error at x=" << x << " y=" << y << "; "
41                    << "actual RGBA=("
42                    << SkColorGetR(actual_color) << ","
43                    << SkColorGetG(actual_color) << ","
44                    << SkColorGetB(actual_color) << ","
45                    << SkColorGetA(actual_color) << "); "
46                    << "expected RGBA=("
47                    << SkColorGetR(expected_color) << ","
48                    << SkColorGetG(expected_color) << ","
49                    << SkColorGetB(expected_color) << ","
50                    << SkColorGetA(expected_color) << ")";
51       }
52     }
53   }
54
55   if (error_pixels_count != 0) {
56     LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
57     return false;
58   }
59
60   return true;
61 }
62
63 FuzzyPixelComparator::FuzzyPixelComparator(
64     const bool discard_alpha,
65     const float error_pixels_percentage_limit,
66     const float small_error_pixels_percentage_limit,
67     const float avg_abs_error_limit,
68     const int max_abs_error_limit,
69     const int small_error_threshold)
70     : discard_alpha_(discard_alpha),
71       error_pixels_percentage_limit_(error_pixels_percentage_limit),
72       small_error_pixels_percentage_limit_(small_error_pixels_percentage_limit),
73       avg_abs_error_limit_(avg_abs_error_limit),
74       max_abs_error_limit_(max_abs_error_limit),
75       small_error_threshold_(small_error_threshold) {
76 }
77
78 bool FuzzyPixelComparator::Compare(const SkBitmap& actual_bmp,
79                                    const SkBitmap& expected_bmp) const {
80   // Number of pixels with an error
81   int error_pixels_count = 0;
82   // Number of pixels with a small error
83   int small_error_pixels_count = 0;
84   // The per channel sums of absolute errors over all pixels.
85   int64 sum_abs_error_r = 0;
86   int64 sum_abs_error_g = 0;
87   int64 sum_abs_error_b = 0;
88   int64 sum_abs_error_a = 0;
89   // The per channel maximum absolute errors over all pixels.
90   int max_abs_error_r = 0;
91   int max_abs_error_g = 0;
92   int max_abs_error_b = 0;
93   int max_abs_error_a = 0;
94
95   // Check that bitmaps have identical dimensions.
96   DCHECK(actual_bmp.width() == expected_bmp.width() &&
97          actual_bmp.height() == expected_bmp.height());
98
99   // Check that bitmaps are not empty.
100   DCHECK(actual_bmp.width() > 0 && actual_bmp.height() > 0);
101
102   SkAutoLockPixels lock_actual_bmp(actual_bmp);
103   SkAutoLockPixels lock_expected_bmp(expected_bmp);
104
105   for (int x = 0; x < actual_bmp.width(); ++x) {
106     for (int y = 0; y < actual_bmp.height(); ++y) {
107       SkColor actual_color = actual_bmp.getColor(x, y);
108       SkColor expected_color = expected_bmp.getColor(x, y);
109       if (discard_alpha_) {
110         actual_color = SkColorSetA(actual_color, 0);
111         expected_color = SkColorSetA(expected_color, 0);
112       }
113
114       if (actual_color != expected_color) {
115         ++error_pixels_count;
116
117         // Compute per channel errors
118         int error_r = SkColorGetR(actual_color) - SkColorGetR(expected_color);
119         int error_g = SkColorGetG(actual_color) - SkColorGetG(expected_color);
120         int error_b = SkColorGetB(actual_color) - SkColorGetB(expected_color);
121         int error_a = SkColorGetA(actual_color) - SkColorGetA(expected_color);
122         int abs_error_r = std::abs(error_r);
123         int abs_error_g = std::abs(error_g);
124         int abs_error_b = std::abs(error_b);
125         int abs_error_a = std::abs(error_a);
126
127         // Increment small error counter if error is below threshold
128         if (abs_error_r <= small_error_threshold_ &&
129             abs_error_g <= small_error_threshold_ &&
130             abs_error_b <= small_error_threshold_ &&
131             abs_error_a <= small_error_threshold_)
132           ++small_error_pixels_count;
133
134         // Update per channel maximum absolute errors
135         max_abs_error_r = std::max(max_abs_error_r, abs_error_r);
136         max_abs_error_g = std::max(max_abs_error_g, abs_error_g);
137         max_abs_error_b = std::max(max_abs_error_b, abs_error_b);
138         max_abs_error_a = std::max(max_abs_error_a, abs_error_a);
139
140         // Update per channel absolute error sums
141         sum_abs_error_r += abs_error_r;
142         sum_abs_error_g += abs_error_g;
143         sum_abs_error_b += abs_error_b;
144         sum_abs_error_a += abs_error_a;
145       }
146     }
147   }
148
149   // Compute error metrics from collected data
150   int pixels_count = actual_bmp.width() * actual_bmp.height();
151   float error_pixels_percentage = 0.0f;
152   float small_error_pixels_percentage = 0.0f;
153   if (pixels_count > 0) {
154     error_pixels_percentage = static_cast<float>(error_pixels_count) /
155         pixels_count * 100.0f;
156     small_error_pixels_percentage =
157         static_cast<float>(small_error_pixels_count) / pixels_count * 100.0f;
158   }
159   float avg_abs_error_r = 0.0f;
160   float avg_abs_error_g = 0.0f;
161   float avg_abs_error_b = 0.0f;
162   float avg_abs_error_a = 0.0f;
163   if (error_pixels_count > 0) {
164     avg_abs_error_r = static_cast<float>(sum_abs_error_r) / error_pixels_count;
165     avg_abs_error_g = static_cast<float>(sum_abs_error_g) / error_pixels_count;
166     avg_abs_error_b = static_cast<float>(sum_abs_error_b) / error_pixels_count;
167     avg_abs_error_a = static_cast<float>(sum_abs_error_a) / error_pixels_count;
168   }
169
170   if (error_pixels_percentage > error_pixels_percentage_limit_ ||
171       small_error_pixels_percentage > small_error_pixels_percentage_limit_ ||
172       avg_abs_error_r > avg_abs_error_limit_ ||
173       avg_abs_error_g > avg_abs_error_limit_ ||
174       avg_abs_error_b > avg_abs_error_limit_ ||
175       avg_abs_error_a > avg_abs_error_limit_ ||
176       max_abs_error_r > max_abs_error_limit_ ||
177       max_abs_error_g > max_abs_error_limit_ ||
178       max_abs_error_b > max_abs_error_limit_ ||
179       max_abs_error_a > max_abs_error_limit_) {
180     LOG(ERROR) << "Percentage of pixels with an error: "
181                << error_pixels_percentage;
182     LOG(ERROR) << "Percentage of pixels with errors not greater than "
183                << small_error_threshold_ << ": "
184                << small_error_pixels_percentage;
185     LOG(ERROR) << "Average absolute error (excluding identical pixels): "
186                << "R=" << avg_abs_error_r << " "
187                << "G=" << avg_abs_error_g << " "
188                << "B=" << avg_abs_error_b << " "
189                << "A=" << avg_abs_error_a;
190     LOG(ERROR) << "Largest absolute error: "
191                << "R=" << max_abs_error_r << " "
192                << "G=" << max_abs_error_g << " "
193                << "B=" << max_abs_error_b << " "
194                << "A=" << max_abs_error_a;
195
196       for (int x = 0; x < actual_bmp.width(); ++x) {
197         for (int y = 0; y < actual_bmp.height(); ++y) {
198           SkColor actual_color = actual_bmp.getColor(x, y);
199           SkColor expected_color = expected_bmp.getColor(x, y);
200           if (discard_alpha_) {
201             actual_color = SkColorSetA(actual_color, 0);
202             expected_color = SkColorSetA(expected_color, 0);
203           }
204           if (actual_color != expected_color) {
205             LOG(ERROR) << "Pixel error at x=" << x << " y=" << y << "; "
206                        << "actual RGBA=("
207                        << SkColorGetR(actual_color) << ","
208                        << SkColorGetG(actual_color) << ","
209                        << SkColorGetB(actual_color) << ","
210                        << SkColorGetA(actual_color) << "); "
211                        << "expected RGBA=("
212                        << SkColorGetR(expected_color) << ","
213                        << SkColorGetG(expected_color) << ","
214                        << SkColorGetB(expected_color) << ","
215                        << SkColorGetA(expected_color) << ")";
216           }
217         }
218       }
219
220     return false;
221   } else {
222     return true;
223   }
224 }
225
226 }  // namespace cc