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"
9 #include "base/logging.h"
13 ExactPixelComparator::ExactPixelComparator(const bool discard_alpha
)
14 : discard_alpha_(discard_alpha
) {
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;
22 // Check that bitmaps have identical dimensions.
23 DCHECK(actual_bmp
.width() == expected_bmp
.width() &&
24 actual_bmp
.height() == expected_bmp
.height());
26 SkAutoLockPixels
lock_actual_bmp(actual_bmp
);
27 SkAutoLockPixels
lock_expected_bmp(expected_bmp
);
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
);
34 actual_color
= SkColorSetA(actual_color
, 0);
35 expected_color
= SkColorSetA(expected_color
, 0);
38 if (actual_color
!= expected_color
) {
40 LOG(ERROR
) << "Pixel error at x=" << x
<< " y=" << y
<< "; "
42 << SkColorGetR(actual_color
) << ","
43 << SkColorGetG(actual_color
) << ","
44 << SkColorGetB(actual_color
) << ","
45 << SkColorGetA(actual_color
) << "); "
47 << SkColorGetR(expected_color
) << ","
48 << SkColorGetG(expected_color
) << ","
49 << SkColorGetB(expected_color
) << ","
50 << SkColorGetA(expected_color
) << ")";
55 if (error_pixels_count
!= 0) {
56 LOG(ERROR
) << "Number of pixel with an error: " << error_pixels_count
;
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
) {
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;
95 // Check that bitmaps have identical dimensions.
96 DCHECK(actual_bmp
.width() == expected_bmp
.width() &&
97 actual_bmp
.height() == expected_bmp
.height());
99 // Check that bitmaps are not empty.
100 DCHECK(actual_bmp
.width() > 0 && actual_bmp
.height() > 0);
102 SkAutoLockPixels
lock_actual_bmp(actual_bmp
);
103 SkAutoLockPixels
lock_expected_bmp(expected_bmp
);
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);
114 if (actual_color
!= expected_color
) {
115 ++error_pixels_count
;
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
);
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
;
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
);
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
;
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
;
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
;
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
;
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);
204 if (actual_color
!= expected_color
) {
205 LOG(ERROR
) << "Pixel error at x=" << x
<< " y=" << y
<< "; "
207 << SkColorGetR(actual_color
) << ","
208 << SkColorGetG(actual_color
) << ","
209 << SkColorGetB(actual_color
) << ","
210 << SkColorGetA(actual_color
) << "); "
212 << SkColorGetR(expected_color
) << ","
213 << SkColorGetG(expected_color
) << ","
214 << SkColorGetB(expected_color
) << ","
215 << SkColorGetA(expected_color
) << ")";