Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1109)

Side by Side Diff: cc/test/pixel_comparator.cc

Issue 12558003: cc: Made image comparison for pixel tests error tolerant. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Introduced PixelComparator interface. Refactored code. Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 bool PixelComparator::CompareSize(const SkBitmap& actual_bmp,
14 const SkBitmap& expected_bmp) const
15 {
reveman 2013/03/07 21:41:25 { should be on previous line
ernstm 2013/03/08 00:14:46 Done.
16 if (actual_bmp.width() != expected_bmp.width() ||
17 actual_bmp.height() != expected_bmp.height()) {
18 LOG(ERROR)
19 << "Dimensions do not match! "
20 << "Actual: " << actual_bmp.width() << "x" << actual_bmp.height() << "; "
reveman 2013/03/07 21:41:25 line too long
ernstm 2013/03/08 00:14:46 Done.
21 << "Expected: " << expected_bmp.width() << "x" << expected_bmp.height() << "";
reveman 2013/03/07 21:41:25 line too long
ernstm 2013/03/08 00:14:46 Done.
22 return false;
23 }
24 return true;
25 }
26
27 bool ExactPixelComparator::Compare(const SkBitmap& actual_bmp,
28 const SkBitmap& expected_bmp) const {
29 // Number of pixels with an error
30 unsigned int error_pixels_count = 0;
31
32 // Bitmaps must have same dimensions
33 if (!CompareSize(actual_bmp, expected_bmp)) return false;
34
35 SkAutoLockPixels lock_actual_bmp(actual_bmp);
36 SkAutoLockPixels lock_expected_bmp(expected_bmp);
37
38 // The reference images were saved with no alpha channel. Use the mask to
39 // set alpha to 0.
40 uint32_t kAlphaMask = 0x00FFFFFF;
41 for (int x = 0; x < actual_bmp.width(); ++x) {
42 for (int y = 0; y < actual_bmp.height(); ++y) {
43 if ((*actual_bmp.getAddr32(x, y) & kAlphaMask) !=
44 (*expected_bmp.getAddr32(x, y) & kAlphaMask)) {
45 ++error_pixels_count;
46 }
47 }
48 }
49
50 if (error_pixels_count != 0) {
51 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count;
52 return false;
53 }
54
55 return true;
56 }
57
58 FuzzyPixelComparator::FuzzyPixelComparator(
59 const float error_pixels_percentage_limit,
60 const float small_error_pixels_percentage_limit,
61 const float avg_abs_error_limit,
62 const unsigned int max_abs_error_limit,
63 const unsigned int small_error_threshold)
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) {
69 }
70
71 bool FuzzyPixelComparator::Compare(const SkBitmap& actual_bmp,
72 const SkBitmap& expected_bmp) const {
73 // Number of pixels with an error
74 unsigned int error_pixels_count = 0;
75 // Number of pixels with a small error
76 unsigned int small_error_pixels_count = 0;
77 // The per channel sums of absolute errors over all pixels.
78 unsigned long long sum_abs_error_r = 0;
reveman 2013/03/07 21:41:25 I think you should use int64/uint64 instead of lon
ernstm 2013/03/08 00:14:46 Done.
79 unsigned long long sum_abs_error_g = 0;
80 unsigned long long sum_abs_error_b = 0;
81 // The per channel maximum absolute errors over all pixels.
82 unsigned int max_abs_error_r = 0;
83 unsigned int max_abs_error_g = 0;
84 unsigned int max_abs_error_b = 0;
85
86 // Bitmaps must have same dimensions
87 if (!CompareSize(actual_bmp, expected_bmp)) return false;
88
89 // Empty bitmaps are always considered to be equal.
90 if (actual_bmp.width() == 0 || actual_bmp.height() == 0) return true;
91
92 SkAutoLockPixels lock_actual_bmp(actual_bmp);
93 SkAutoLockPixels lock_expected_bmp(expected_bmp);
94
95 // The reference images were saved with no alpha channel. Use the mask to
96 // set alpha to 0.
97 uint32_t kAlphaMask = 0x00FFFFFF;
reveman 2013/03/07 21:41:25 This makes assumptions about the pixel format used
ernstm 2013/03/08 00:14:46 Modified to use SkColorSetA instead instead of dir
98 for (int x = 0; x < actual_bmp.width(); ++x) {
99 for (int y = 0; y < actual_bmp.height(); ++y) {
100 if ((*actual_bmp.getAddr32(x, y) & kAlphaMask) !=
101 (*expected_bmp.getAddr32(x, y) & kAlphaMask)) {
102 ++error_pixels_count;
103
104 SkColor color_a = actual_bmp.getColor(x, y);
105 SkColor color_b = expected_bmp.getColor(x, y);
106
107 // Compute per channel absolute errors
108 unsigned int abs_error_r =
109 std::max(SkColorGetR(color_a), SkColorGetR(color_b)) -
110 std::min(SkColorGetR(color_a), SkColorGetR(color_b));
111 unsigned int abs_error_g =
112 std::max(SkColorGetG(color_a), SkColorGetG(color_b)) -
113 std::min(SkColorGetG(color_a), SkColorGetG(color_b));
114 unsigned int abs_error_b =
115 std::max(SkColorGetB(color_a), SkColorGetB(color_b)) -
116 std::min(SkColorGetB(color_a), SkColorGetB(color_b));
117
118 // Increment small error counter if error is below threshold
119 if (abs_error_r <= small_error_threshold_ &&
120 abs_error_g <= small_error_threshold_ &&
121 abs_error_b <= small_error_threshold_)
122 ++small_error_pixels_count;
123
124 // Update per channel maximum absolute errors
125 if (abs_error_r > max_abs_error_r) max_abs_error_r = abs_error_r;
126 if (abs_error_g > max_abs_error_g) max_abs_error_g = abs_error_g;
127 if (abs_error_b > max_abs_error_b) max_abs_error_b = abs_error_b;
128
129 // Update per channel absolute error sums
130 sum_abs_error_r += abs_error_r;
131 sum_abs_error_g += abs_error_g;
132 sum_abs_error_b += abs_error_b;
133 }
134 }
135 }
136
137 // Compute error metrics from collected data
138 unsigned int pixels_count = actual_bmp.width() * actual_bmp.height();
139 float error_pixels_percentage = static_cast<float>(error_pixels_count) /
140 pixels_count * 100.0f;
141 float small_error_pixels_percentage = static_cast<float>(small_error_pixels_co unt) /
reveman 2013/03/07 21:41:25 line too long
ernstm 2013/03/08 00:14:46 Done.
142 pixels_count * 100.0f;
143 float avg_abs_error_r;
144 float avg_abs_error_g;
145 float avg_abs_error_b;
146 if (error_pixels_count > 0) {
147 avg_abs_error_r = static_cast<float>(sum_abs_error_r) / error_pixels_count;
148 avg_abs_error_g = static_cast<float>(sum_abs_error_g) / error_pixels_count;
149 avg_abs_error_b = static_cast<float>(sum_abs_error_b) / error_pixels_count;
150 } else {
151 avg_abs_error_r = 0;
152 avg_abs_error_g = 0;
153 avg_abs_error_b = 0;
154 }
155
156 if (error_pixels_percentage > error_pixels_percentage_limit_ ||
157 small_error_pixels_percentage > small_error_pixels_percentage_limit_ ||
158 avg_abs_error_r > avg_abs_error_limit_ ||
159 avg_abs_error_g > avg_abs_error_limit_ ||
160 avg_abs_error_b > avg_abs_error_limit_ ||
161 max_abs_error_r > max_abs_error_limit_ ||
162 max_abs_error_g > max_abs_error_limit_ ||
163 max_abs_error_b > max_abs_error_limit_) {
164 LOG(ERROR) << "Percentage of pixels with an error: "
165 << error_pixels_percentage << "; "
166 << "Percentage of pixels with errors not greater than "
167 << small_error_threshold_ << ": "
168 << small_error_pixels_percentage << "; "
169 << "Average absolute error (excluding identical pixels): "
170 << "R=" << avg_abs_error_r << " "
171 << "G=" << avg_abs_error_g << " "
172 << "B=" << avg_abs_error_b << "; "
173 << "Largest absolute error: "
174 << "R=" << max_abs_error_r << " "
175 << "G=" << max_abs_error_g << " "
176 << "B=" << max_abs_error_b;
177 return false;
178 } else {
179 return true;
180 }
181 }
182
183 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698