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"
10 #include "ui/gfx/geometry/rect.h"
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
);
37 actual_color
= SkColorSetA(actual_color
, 0);
38 expected_color
= SkColorSetA(expected_color
, 0);
40 if (actual_color
!= expected_color
) {
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();
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();