Adding Peter Thatcher to the owners file.
[chromium-blink-merge.git] / cc / test / pixel_comparator.cc
blob4067787cef569c2b472608f2081e762a2c1e4753
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.
5 #include "cc/test/pixel_comparator.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "ui/gfx/geometry/rect.h"
12 namespace cc {
14 ExactPixelComparator::ExactPixelComparator(const bool discard_alpha)
15 : discard_alpha_(discard_alpha) {
18 bool ExactPixelComparator::Compare(const SkBitmap& actual_bmp,
19 const SkBitmap& expected_bmp) const {
20 // Number of pixels with an error
21 int error_pixels_count = 0;
23 gfx::Rect error_bounding_rect = gfx::Rect();
25 // Check that bitmaps have identical dimensions.
26 DCHECK(actual_bmp.width() == expected_bmp.width() &&
27 actual_bmp.height() == expected_bmp.height());
29 SkAutoLockPixels lock_actual_bmp(actual_bmp);
30 SkAutoLockPixels lock_expected_bmp(expected_bmp);
32 for (int x = 0; x < actual_bmp.width(); ++x) {
33 for (int y = 0; y < actual_bmp.height(); ++y) {
34 SkColor actual_color = actual_bmp.getColor(x, y);
35 SkColor expected_color = expected_bmp.getColor(x, y);
36 if (discard_alpha_) {
37 actual_color = SkColorSetA(actual_color, 0);
38 expected_color = SkColorSetA(expected_color, 0);
40 if (actual_color != expected_color) {
41 ++error_pixels_count;
42 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
47 if (error_pixels_count != 0) {
48 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
49 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
50 return false;
53 return true;
56 FuzzyPixelComparator::FuzzyPixelComparator(
57 const bool discard_alpha,
58 const float error_pixels_percentage_limit,
59 const float small_error_pixels_percentage_limit,
60 const float avg_abs_error_limit,
61 const int max_abs_error_limit,
62 const int small_error_threshold)
63 : discard_alpha_(discard_alpha),
64 error_pixels_percentage_limit_(error_pixels_percentage_limit),
65 small_error_pixels_percentage_limit_(small_error_pixels_percentage_limit),
66 avg_abs_error_limit_(avg_abs_error_limit),
67 max_abs_error_limit_(max_abs_error_limit),
68 small_error_threshold_(small_error_threshold) {
71 bool FuzzyPixelComparator::Compare(const SkBitmap& actual_bmp,
72 const SkBitmap& expected_bmp) const {
73 // Number of pixels with an error
74 int error_pixels_count = 0;
75 // Number of pixels with a small error
76 int small_error_pixels_count = 0;
77 // The per channel sums of absolute errors over all pixels.
78 int64 sum_abs_error_r = 0;
79 int64 sum_abs_error_g = 0;
80 int64 sum_abs_error_b = 0;
81 int64 sum_abs_error_a = 0;
82 // The per channel maximum absolute errors over all pixels.
83 int max_abs_error_r = 0;
84 int max_abs_error_g = 0;
85 int max_abs_error_b = 0;
86 int max_abs_error_a = 0;
88 gfx::Rect error_bounding_rect = gfx::Rect();
90 // Check that bitmaps have identical dimensions.
91 DCHECK(actual_bmp.width() == expected_bmp.width() &&
92 actual_bmp.height() == expected_bmp.height());
94 // Check that bitmaps are not empty.
95 DCHECK(actual_bmp.width() > 0 && actual_bmp.height() > 0);
97 SkAutoLockPixels lock_actual_bmp(actual_bmp);
98 SkAutoLockPixels lock_expected_bmp(expected_bmp);
100 for (int x = 0; x < actual_bmp.width(); ++x) {
101 for (int y = 0; y < actual_bmp.height(); ++y) {
102 SkColor actual_color = actual_bmp.getColor(x, y);
103 SkColor expected_color = expected_bmp.getColor(x, y);
104 if (discard_alpha_) {
105 actual_color = SkColorSetA(actual_color, 0);
106 expected_color = SkColorSetA(expected_color, 0);
109 if (actual_color != expected_color) {
110 ++error_pixels_count;
112 // Compute per channel errors
113 int error_r = SkColorGetR(actual_color) - SkColorGetR(expected_color);
114 int error_g = SkColorGetG(actual_color) - SkColorGetG(expected_color);
115 int error_b = SkColorGetB(actual_color) - SkColorGetB(expected_color);
116 int error_a = SkColorGetA(actual_color) - SkColorGetA(expected_color);
117 int abs_error_r = std::abs(error_r);
118 int abs_error_g = std::abs(error_g);
119 int abs_error_b = std::abs(error_b);
120 int abs_error_a = std::abs(error_a);
122 // Increment small error counter if error is below threshold
123 if (abs_error_r <= small_error_threshold_ &&
124 abs_error_g <= small_error_threshold_ &&
125 abs_error_b <= small_error_threshold_ &&
126 abs_error_a <= small_error_threshold_)
127 ++small_error_pixels_count;
129 // Update per channel maximum absolute errors
130 max_abs_error_r = std::max(max_abs_error_r, abs_error_r);
131 max_abs_error_g = std::max(max_abs_error_g, abs_error_g);
132 max_abs_error_b = std::max(max_abs_error_b, abs_error_b);
133 max_abs_error_a = std::max(max_abs_error_a, abs_error_a);
135 // Update per channel absolute error sums
136 sum_abs_error_r += abs_error_r;
137 sum_abs_error_g += abs_error_g;
138 sum_abs_error_b += abs_error_b;
139 sum_abs_error_a += abs_error_a;
144 // Compute error metrics from collected data
145 int pixels_count = actual_bmp.width() * actual_bmp.height();
146 float error_pixels_percentage = 0.0f;
147 float small_error_pixels_percentage = 0.0f;
148 if (pixels_count > 0) {
149 error_pixels_percentage = static_cast<float>(error_pixels_count) /
150 pixels_count * 100.0f;
151 small_error_pixels_percentage =
152 static_cast<float>(small_error_pixels_count) / pixels_count * 100.0f;
154 float avg_abs_error_r = 0.0f;
155 float avg_abs_error_g = 0.0f;
156 float avg_abs_error_b = 0.0f;
157 float avg_abs_error_a = 0.0f;
158 if (error_pixels_count > 0) {
159 avg_abs_error_r = static_cast<float>(sum_abs_error_r) / error_pixels_count;
160 avg_abs_error_g = static_cast<float>(sum_abs_error_g) / error_pixels_count;
161 avg_abs_error_b = static_cast<float>(sum_abs_error_b) / error_pixels_count;
162 avg_abs_error_a = static_cast<float>(sum_abs_error_a) / error_pixels_count;
165 if (error_pixels_percentage > error_pixels_percentage_limit_ ||
166 small_error_pixels_percentage > small_error_pixels_percentage_limit_ ||
167 avg_abs_error_r > avg_abs_error_limit_ ||
168 avg_abs_error_g > avg_abs_error_limit_ ||
169 avg_abs_error_b > avg_abs_error_limit_ ||
170 avg_abs_error_a > avg_abs_error_limit_ ||
171 max_abs_error_r > max_abs_error_limit_ ||
172 max_abs_error_g > max_abs_error_limit_ ||
173 max_abs_error_b > max_abs_error_limit_ ||
174 max_abs_error_a > max_abs_error_limit_) {
175 LOG(ERROR) << "Percentage of pixels with an error: "
176 << error_pixels_percentage;
177 LOG(ERROR) << "Percentage of pixels with errors not greater than "
178 << small_error_threshold_ << ": "
179 << small_error_pixels_percentage;
180 LOG(ERROR) << "Average absolute error (excluding identical pixels): "
181 << "R=" << avg_abs_error_r << " "
182 << "G=" << avg_abs_error_g << " "
183 << "B=" << avg_abs_error_b << " "
184 << "A=" << avg_abs_error_a;
185 LOG(ERROR) << "Largest absolute error: "
186 << "R=" << max_abs_error_r << " "
187 << "G=" << max_abs_error_g << " "
188 << "B=" << max_abs_error_b << " "
189 << "A=" << max_abs_error_a;
191 for (int x = 0; x < actual_bmp.width(); ++x) {
192 for (int y = 0; y < actual_bmp.height(); ++y) {
193 SkColor actual_color = actual_bmp.getColor(x, y);
194 SkColor expected_color = expected_bmp.getColor(x, y);
195 if (discard_alpha_) {
196 actual_color = SkColorSetA(actual_color, 0);
197 expected_color = SkColorSetA(expected_color, 0);
199 if (actual_color != expected_color)
200 error_bounding_rect.Union(gfx::Rect(x, y, 1, 1));
203 LOG(ERROR) << "Error Bounding Box : " << error_bounding_rect.ToString();
204 return false;
205 } else {
206 return true;
210 } // namespace cc