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 ExactPixelComparator::ExactPixelComparator(const bool discard_alpha) 14 : discard_alpha_(discard_alpha) { 15 } 16 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; 21 22 // Check that bitmaps have identical dimensions. 23 DCHECK(actual_bmp.width() == expected_bmp.width() && 24 actual_bmp.height() == expected_bmp.height()); 25 26 SkAutoLockPixels lock_actual_bmp(actual_bmp); 27 SkAutoLockPixels lock_expected_bmp(expected_bmp); 28 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); 33 if (discard_alpha_) { 34 actual_color = SkColorSetA(actual_color, 0); 35 expected_color = SkColorSetA(expected_color, 0); 36 } 37 38 if (actual_color != expected_color) { 39 ++error_pixels_count; 40 LOG(ERROR) << "Pixel error at x=" << x << " y=" << y << "; " 41 << "actual RGBA=(" 42 << SkColorGetR(actual_color) << "," 43 << SkColorGetG(actual_color) << "," 44 << SkColorGetB(actual_color) << "," 45 << SkColorGetA(actual_color) << "); " 46 << "expected RGBA=(" 47 << SkColorGetR(expected_color) << "," 48 << SkColorGetG(expected_color) << "," 49 << SkColorGetB(expected_color) << "," 50 << SkColorGetA(expected_color) << ")"; 51 } 52 } 53 } 54 55 if (error_pixels_count != 0) { 56 LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; 57 return false; 58 } 59 60 return true; 61 } 62 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) { 76 } 77 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; 94 95 // Check that bitmaps have identical dimensions. 96 DCHECK(actual_bmp.width() == expected_bmp.width() && 97 actual_bmp.height() == expected_bmp.height()); 98 99 // Check that bitmaps are not empty. 100 DCHECK(actual_bmp.width() > 0 && actual_bmp.height() > 0); 101 102 SkAutoLockPixels lock_actual_bmp(actual_bmp); 103 SkAutoLockPixels lock_expected_bmp(expected_bmp); 104 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); 112 } 113 114 if (actual_color != expected_color) { 115 ++error_pixels_count; 116 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); 126 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; 133 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); 139 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; 145 } 146 } 147 } 148 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; 158 } 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; 168 } 169 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; 195 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); 203 } 204 if (actual_color != expected_color) { 205 LOG(ERROR) << "Pixel error at x=" << x << " y=" << y << "; " 206 << "actual RGBA=(" 207 << SkColorGetR(actual_color) << "," 208 << SkColorGetG(actual_color) << "," 209 << SkColorGetB(actual_color) << "," 210 << SkColorGetA(actual_color) << "); " 211 << "expected RGBA=(" 212 << SkColorGetR(expected_color) << "," 213 << SkColorGetG(expected_color) << "," 214 << SkColorGetB(expected_color) << "," 215 << SkColorGetA(expected_color) << ")"; 216 } 217 } 218 } 219 220 return false; 221 } else { 222 return true; 223 } 224 } 225 226 } // namespace cc 227