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

Side by Side Diff: cc/test/image_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: 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/image_comparator.h"
6
7 #include <algorithm>
8
9 namespace cc {
10
11 ImageComparator::ImageComparator() {
12 thresholds_ = ErrorMetrics();
13 }
14
15 ImageComparator::ImageComparator(const ErrorMetrics& thresholds)
16 : thresholds_(thresholds)
17 { }
18
19 ImageComparator::ErrorMetrics::ErrorMetrics(float error_pixels_percentage,
20 float small_error_pixels_percentage,
21 float avg_abs_error_r,
22 float avg_abs_error_g,
23 float avg_abs_error_b,
24 unsigned int max_abs_error_r,
25 unsigned int max_abs_error_g,
26 unsigned int max_abs_error_b,
27 unsigned int small_error_threshold)
28 : error_pixels_percentage(error_pixels_percentage),
29 small_error_pixels_percentage(small_error_pixels_percentage),
30 avg_abs_error_r(avg_abs_error_r),
31 avg_abs_error_g(avg_abs_error_g),
32 avg_abs_error_b(avg_abs_error_b),
33 max_abs_error_r(max_abs_error_r),
34 max_abs_error_g(max_abs_error_g),
35 max_abs_error_b(max_abs_error_b),
36 small_error_threshold(small_error_threshold)
37 { }
38
39 void ImageComparator::AllowOffByOneErrors(float off_by_one_pixels_percentage) {
40 thresholds_.error_pixels_percentage = off_by_one_pixels_percentage;
41 thresholds_.small_error_pixels_percentage = off_by_one_pixels_percentage;
42 thresholds_.avg_abs_error_r = 1.0f;
43 thresholds_.avg_abs_error_g = 1.0f;
44 thresholds_.avg_abs_error_b = 1.0f;
45 thresholds_.max_abs_error_r = 1.0f;
46 thresholds_.max_abs_error_g = 1.0f;
47 thresholds_.max_abs_error_b = 1.0f;
48 thresholds_.small_error_threshold = 1;
49 }
50
51 bool ImageComparator::Compare(const SkBitmap& bitmap_a,
52 const SkBitmap& bitmap_b,
53 ErrorMetrics* return_metrics) const {
54 ErrorMetrics metrics;
55 metrics.small_error_threshold = thresholds_.small_error_threshold;
56
57 // Number of pixels that are different.
58 unsigned int error_pixels_count = 0;
59 // Number of pixels that are at most off by small_error_threshold per color
60 // channel
61 unsigned int small_error_pixels_count = 0;
62 // The per channel sum of absolute errors over all pixels.
63 unsigned long long sum_abs_error_r = 0;
64 unsigned long long sum_abs_error_g = 0;
65 unsigned long long sum_abs_error_b = 0;
66
67 // A meaningful comparison is not possible if the size does not match
68 // (alignment? background color?). Return maximum error values in that case.
69 if (bitmap_a.width() != bitmap_b.width() ||
70 bitmap_a.height() != bitmap_b.height()) {
reveman 2013/03/07 07:50:44 MatchesPNGFile already check the size. DCHECK is e
ernstm 2013/03/07 19:30:07 Moved all dimension checking into Compare function
71 if (return_metrics != NULL) {
72 return_metrics->error_pixels_percentage = 100.0f;
73 return_metrics->small_error_pixels_percentage = 0.0f;
74 return_metrics->avg_abs_error_r = 255.0f;
75 return_metrics->avg_abs_error_g = 255.0f;
76 return_metrics->avg_abs_error_b = 255.0f;
77 return_metrics->max_abs_error_r = 255;
78 return_metrics->max_abs_error_g = 255;
79 return_metrics->max_abs_error_b = 255;
80 return_metrics->small_error_threshold = thresholds_.small_error_threshold;
81 }
82 return false;
83 }
84
85 // Empty bitmaps are always considered to be equal.
86 if (bitmap_a.width() == 0 || bitmap_a.height() == 0) {
reveman 2013/03/07 07:50:44 move this to MatchesPNGFile if needed. DCHECK at m
ernstm 2013/03/07 19:30:07 This got much simpler in the refactored code. On 2
87 if (return_metrics != NULL) {
88 return_metrics->error_pixels_percentage = 0.0f;
89 return_metrics->small_error_pixels_percentage = 0.0f;
90 return_metrics->avg_abs_error_r = 0.0f;
91 return_metrics->avg_abs_error_g = 0.0f;
92 return_metrics->avg_abs_error_b = 0.0f;
93 return_metrics->max_abs_error_r = 0;
94 return_metrics->max_abs_error_g = 0;
95 return_metrics->max_abs_error_b = 0;
96 return_metrics->small_error_threshold = thresholds_.small_error_threshold;
97 }
98 return true;
99 }
100
101 SkAutoLockPixels lock_bitmap_a(bitmap_a);
102 SkAutoLockPixels lock_bitmap_b(bitmap_b);
103
104 // The reference images were saved with no alpha channel. Use the mask to
105 // set alpha to 0.
106 uint32_t kAlphaMask = 0x00FFFFFF;
107 for (int x = 0; x < bitmap_a.width(); ++x) {
108 for (int y = 0; y < bitmap_a.height(); ++y) {
109 if ((*bitmap_a.getAddr32(x, y) & kAlphaMask) !=
110 (*bitmap_b.getAddr32(x, y) & kAlphaMask)) {
111 ++error_pixels_count;
112
113 SkColor color_a = bitmap_a.getColor(x, y);
114 SkColor color_b = bitmap_b.getColor(x, y);
115
116 // Compute per channel absolute errors
117 unsigned int abs_error_r =
118 std::max(SkColorGetR(color_a), SkColorGetR(color_b)) -
119 std::min(SkColorGetR(color_a), SkColorGetR(color_b));
120 unsigned int abs_error_g =
121 std::max(SkColorGetG(color_a), SkColorGetG(color_b)) -
122 std::min(SkColorGetG(color_a), SkColorGetG(color_b));
123 unsigned int abs_error_b =
124 std::max(SkColorGetB(color_a), SkColorGetB(color_b)) -
125 std::min(SkColorGetB(color_a), SkColorGetB(color_b));
126
127 // Increment small error counter if error is below threshold
128 if (abs_error_r <= thresholds_.small_error_threshold &&
129 abs_error_g <= thresholds_.small_error_threshold &&
130 abs_error_b <= thresholds_.small_error_threshold)
131 ++small_error_pixels_count;
132
133 // Update per channel maximum absolute errors
134 if (abs_error_r > metrics.max_abs_error_r)
135 metrics.max_abs_error_r = abs_error_r;
136 if (abs_error_g > metrics.max_abs_error_g)
137 metrics.max_abs_error_g = abs_error_g;
138 if (abs_error_b > metrics.max_abs_error_b)
139 metrics.max_abs_error_b = abs_error_b;
140
141 // Update per channel absolute error sums
142 sum_abs_error_r += abs_error_r;
143 sum_abs_error_g += abs_error_g;
144 sum_abs_error_b += abs_error_b;
145 }
146 }
147 }
148
149 // Fill error metrics with collected data
150 unsigned int pixels_count = bitmap_a.width() * bitmap_a.height();
151 metrics.error_pixels_percentage = static_cast<float>(error_pixels_count) /
152 pixels_count * 100.0f;
153 metrics.small_error_pixels_percentage = static_cast<float>(small_error_pixels_ count) /
154 pixels_count * 100.0f;
155 if (error_pixels_count > 0) {
156 metrics.avg_abs_error_r = static_cast<float>(sum_abs_error_r) / error_pixels _count;
157 metrics.avg_abs_error_g = static_cast<float>(sum_abs_error_g) / error_pixels _count;
158 metrics.avg_abs_error_b = static_cast<float>(sum_abs_error_b) / error_pixels _count;
159 } else {
160 metrics.avg_abs_error_r = 0;
161 metrics.avg_abs_error_g = 0;
162 metrics.avg_abs_error_b = 0;
163 }
164
165 // Return error_ etrics using passed in pointer if not NULL
166 if (return_metrics != NULL) *return_metrics = metrics;
167
168 // Return true if all collected error metrics are below the comparator's thres holds.
169 return (metrics.error_pixels_percentage <= thresholds_.error_pixels_percentage &&
170 metrics.small_error_pixels_percentage <= thresholds_.small_error_pixel s_percentage &&
171 metrics.avg_abs_error_r <= thresholds_.avg_abs_error_r &&
172 metrics.avg_abs_error_g <= thresholds_.avg_abs_error_g &&
173 metrics.avg_abs_error_b <= thresholds_.avg_abs_error_b &&
174 metrics.max_abs_error_r <= thresholds_.max_abs_error_r &&
175 metrics.max_abs_error_g <= thresholds_.max_abs_error_g &&
176 metrics.max_abs_error_b <= thresholds_.max_abs_error_b);
177 }
178
179 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698