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 SkColorSetA(actual_color
, 0);
35 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 SkColorSetA(actual_color
, 0);
111 SkColorSetA(expected_color
, 0);
114 if (actual_color
!= expected_color
) {
115 ++error_pixels_count
;
117 LOG(ERROR
) << "Pixel error at x=" << x
<< " y=" << y
<< "; "
119 << SkColorGetR(actual_color
) << ","
120 << SkColorGetG(actual_color
) << ","
121 << SkColorGetB(actual_color
) << ","
122 << SkColorGetA(actual_color
) << "); "
124 << SkColorGetR(expected_color
) << ","
125 << SkColorGetG(expected_color
) << ","
126 << SkColorGetB(expected_color
) << ","
127 << SkColorGetA(expected_color
) << ")";
129 // Compute per channel errors
130 int error_r
= SkColorGetR(actual_color
) - SkColorGetR(expected_color
);
131 int error_g
= SkColorGetG(actual_color
) - SkColorGetG(expected_color
);
132 int error_b
= SkColorGetB(actual_color
) - SkColorGetB(expected_color
);
133 int error_a
= SkColorGetA(actual_color
) - SkColorGetA(expected_color
);
134 int abs_error_r
= std::abs(error_r
);
135 int abs_error_g
= std::abs(error_g
);
136 int abs_error_b
= std::abs(error_b
);
137 int abs_error_a
= std::abs(error_a
);
139 // Increment small error counter if error is below threshold
140 if (abs_error_r
<= small_error_threshold_
&&
141 abs_error_g
<= small_error_threshold_
&&
142 abs_error_b
<= small_error_threshold_
&&
143 abs_error_a
<= small_error_threshold_
)
144 ++small_error_pixels_count
;
146 // Update per channel maximum absolute errors
147 max_abs_error_r
= std::max(max_abs_error_r
, abs_error_r
);
148 max_abs_error_g
= std::max(max_abs_error_g
, abs_error_g
);
149 max_abs_error_b
= std::max(max_abs_error_b
, abs_error_b
);
150 max_abs_error_a
= std::max(max_abs_error_a
, abs_error_a
);
152 // Update per channel absolute error sums
153 sum_abs_error_r
+= abs_error_r
;
154 sum_abs_error_g
+= abs_error_g
;
155 sum_abs_error_b
+= abs_error_b
;
156 sum_abs_error_a
+= abs_error_a
;
161 // Compute error metrics from collected data
162 int pixels_count
= actual_bmp
.width() * actual_bmp
.height();
163 float error_pixels_percentage
= 0.0f
;
164 float small_error_pixels_percentage
= 0.0f
;
165 if (pixels_count
> 0) {
166 error_pixels_percentage
= static_cast<float>(error_pixels_count
) /
167 pixels_count
* 100.0f
;
168 small_error_pixels_percentage
=
169 static_cast<float>(small_error_pixels_count
) / pixels_count
* 100.0f
;
171 float avg_abs_error_r
= 0.0f
;
172 float avg_abs_error_g
= 0.0f
;
173 float avg_abs_error_b
= 0.0f
;
174 float avg_abs_error_a
= 0.0f
;
175 if (error_pixels_count
> 0) {
176 avg_abs_error_r
= static_cast<float>(sum_abs_error_r
) / error_pixels_count
;
177 avg_abs_error_g
= static_cast<float>(sum_abs_error_g
) / error_pixels_count
;
178 avg_abs_error_b
= static_cast<float>(sum_abs_error_b
) / error_pixels_count
;
179 avg_abs_error_a
= static_cast<float>(sum_abs_error_a
) / error_pixels_count
;
182 if (error_pixels_percentage
> error_pixels_percentage_limit_
||
183 small_error_pixels_percentage
> small_error_pixels_percentage_limit_
||
184 avg_abs_error_r
> avg_abs_error_limit_
||
185 avg_abs_error_g
> avg_abs_error_limit_
||
186 avg_abs_error_b
> avg_abs_error_limit_
||
187 avg_abs_error_a
> avg_abs_error_limit_
||
188 max_abs_error_r
> max_abs_error_limit_
||
189 max_abs_error_g
> max_abs_error_limit_
||
190 max_abs_error_b
> max_abs_error_limit_
||
191 max_abs_error_a
> max_abs_error_limit_
) {
192 LOG(ERROR
) << "Percentage of pixels with an error: "
193 << error_pixels_percentage
;
194 LOG(ERROR
) << "Percentage of pixels with errors not greater than "
195 << small_error_threshold_
<< ": "
196 << small_error_pixels_percentage
;
197 LOG(ERROR
) << "Average absolute error (excluding identical pixels): "
198 << "R=" << avg_abs_error_r
<< " "
199 << "G=" << avg_abs_error_g
<< " "
200 << "B=" << avg_abs_error_b
<< " "
201 << "A=" << avg_abs_error_a
;
202 LOG(ERROR
) << "Largest absolute error: "
203 << "R=" << max_abs_error_r
<< " "
204 << "G=" << max_abs_error_g
<< " "
205 << "B=" << max_abs_error_b
<< " "
206 << "A=" << max_abs_error_a
;