Index: cc/test/pixel_comparator.cc |
diff --git a/cc/test/pixel_comparator.cc b/cc/test/pixel_comparator.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..efe048725dd7e958a2d2b99811310d5efc0f27d2 |
--- /dev/null |
+++ b/cc/test/pixel_comparator.cc |
@@ -0,0 +1,174 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "cc/test/pixel_comparator.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/logging.h" |
+ |
+namespace cc { |
+ |
+bool ExactPixelComparator::Compare(const SkBitmap& actual_bmp, |
+ const SkBitmap& expected_bmp) const { |
+ // Number of pixels with an error |
+ int error_pixels_count = 0; |
+ |
+ // Check that bitmaps have identical dimensions. |
+ DCHECK(actual_bmp.width() == expected_bmp.width() && |
+ actual_bmp.height() == expected_bmp.height()); |
+ |
+ SkAutoLockPixels lock_actual_bmp(actual_bmp); |
+ SkAutoLockPixels lock_expected_bmp(expected_bmp); |
+ |
+ for (int x = 0; x < actual_bmp.width(); ++x) { |
+ for (int y = 0; y < actual_bmp.height(); ++y) { |
+ // Fetch color values. Set alpha to 0, because rhe reference images were |
+ // saved with no alpha channel. |
+ SkColor actual_color = actual_bmp.getColor(x, y); |
+ SkColorSetA(actual_color, 0); |
+ SkColor expected_color = expected_bmp.getColor(x, y); |
+ SkColorSetA(expected_color, 0); |
+ |
+ if (actual_color != expected_color) { |
+ ++error_pixels_count; |
+ } |
+ } |
+ } |
+ |
+ if (error_pixels_count != 0) { |
+ LOG(ERROR) << "Number of pixel with an error: " << error_pixels_count; |
+ return false; |
+ } |
+ |
+ return true; |
+} |
+ |
+FuzzyPixelComparator::FuzzyPixelComparator( |
+ const float error_pixels_percentage_limit, |
+ const float small_error_pixels_percentage_limit, |
+ const float avg_abs_error_limit, |
+ const int max_abs_error_limit, |
+ const int small_error_threshold) |
+ : error_pixels_percentage_limit_(error_pixels_percentage_limit), |
+ small_error_pixels_percentage_limit_(small_error_pixels_percentage_limit), |
+ avg_abs_error_limit_(avg_abs_error_limit), |
+ max_abs_error_limit_(max_abs_error_limit), |
+ small_error_threshold_(small_error_threshold) { |
+} |
+ |
+bool FuzzyPixelComparator::Compare(const SkBitmap& actual_bmp, |
+ const SkBitmap& expected_bmp) const { |
+ // Number of pixels with an error |
+ int error_pixels_count = 0; |
+ // Number of pixels with a small error |
+ int small_error_pixels_count = 0; |
+ // The per channel sums of absolute errors over all pixels. |
+ int64 sum_abs_error_r = 0; |
+ int64 sum_abs_error_g = 0; |
+ int64 sum_abs_error_b = 0; |
+ // The per channel maximum absolute errors over all pixels. |
+ int max_abs_error_r = 0; |
+ int max_abs_error_g = 0; |
+ int max_abs_error_b = 0; |
+ |
+ // Check that bitmaps have identical dimensions. |
+ DCHECK(actual_bmp.width() == expected_bmp.width() && |
+ actual_bmp.height() == expected_bmp.height()); |
+ |
+ // Check that bitmaps are not empty. |
+ DCHECK(actual_bmp.width() > 0 && actual_bmp.height() > 0); |
+ |
+ SkAutoLockPixels lock_actual_bmp(actual_bmp); |
+ SkAutoLockPixels lock_expected_bmp(expected_bmp); |
+ |
+ for (int x = 0; x < actual_bmp.width(); ++x) { |
+ for (int y = 0; y < actual_bmp.height(); ++y) { |
+ // Fetch color values. Set alpha to 0, because rhe reference images were |
+ // saved with no alpha channel. |
+ SkColor actual_color = actual_bmp.getColor(x, y); |
+ SkColorSetA(actual_color, 0); |
+ SkColor expected_color = expected_bmp.getColor(x, y); |
+ SkColorSetA(expected_color, 0); |
+ |
+ if (actual_color != expected_color) { |
+ ++error_pixels_count; |
+ |
+ // Compute per channel absolute errors |
+ int abs_error_r = |
+ std::max(SkColorGetR(actual_color), SkColorGetR(expected_color)) - |
slavi
2013/03/08 19:49:04
Why not
std::abs(SkColorGetR(actual_color) - SkCo
ernstm
2013/03/18 20:19:39
Done.
|
+ std::min(SkColorGetR(actual_color), SkColorGetR(expected_color)); |
+ int abs_error_g = |
+ std::max(SkColorGetG(actual_color), SkColorGetG(expected_color)) - |
+ std::min(SkColorGetG(actual_color), SkColorGetG(expected_color)); |
+ int abs_error_b = |
+ std::max(SkColorGetB(actual_color), SkColorGetB(expected_color)) - |
+ std::min(SkColorGetB(actual_color), SkColorGetB(expected_color)); |
+ |
+ // Increment small error counter if error is below threshold |
+ if (abs_error_r <= small_error_threshold_ && |
+ abs_error_g <= small_error_threshold_ && |
+ abs_error_b <= small_error_threshold_) |
+ ++small_error_pixels_count; |
+ |
+ // Update per channel maximum absolute errors |
+ if (abs_error_r > max_abs_error_r) max_abs_error_r = abs_error_r; |
slavi
2013/03/08 19:49:04
max_abs_error_r = std::max(max_abs_error_r, abs_er
ernstm
2013/03/18 20:19:39
Done.
|
+ if (abs_error_g > max_abs_error_g) max_abs_error_g = abs_error_g; |
+ if (abs_error_b > max_abs_error_b) max_abs_error_b = abs_error_b; |
reveman
2013/03/08 04:41:57
nit: put max_abs_error_? = abs_error_?; statements
ernstm
2013/03/18 20:19:39
Done.
|
+ |
+ // Update per channel absolute error sums |
+ sum_abs_error_r += abs_error_r; |
+ sum_abs_error_g += abs_error_g; |
+ sum_abs_error_b += abs_error_b; |
+ } |
+ } |
+ } |
+ |
+ // Compute error metrics from collected data |
+ int pixels_count = actual_bmp.width() * actual_bmp.height(); |
+ float error_pixels_percentage = 0.0f; |
+ float small_error_pixels_percentage = 0.0f; |
+ if (pixels_count > 0) { |
+ error_pixels_percentage = static_cast<float>(error_pixels_count) / |
+ pixels_count * 100.0f; |
+ small_error_pixels_percentage = |
+ static_cast<float>(small_error_pixels_count) / pixels_count * 100.0f; |
+ } |
+ float avg_abs_error_r = 0.0f; |
+ float avg_abs_error_g = 0.0f; |
+ float avg_abs_error_b = 0.0f; |
+ if (error_pixels_count > 0) { |
+ avg_abs_error_r = static_cast<float>(sum_abs_error_r) / error_pixels_count; |
+ avg_abs_error_g = static_cast<float>(sum_abs_error_g) / error_pixels_count; |
+ avg_abs_error_b = static_cast<float>(sum_abs_error_b) / error_pixels_count; |
+ } |
+ |
+ if (error_pixels_percentage > error_pixels_percentage_limit_ || |
+ small_error_pixels_percentage > small_error_pixels_percentage_limit_ || |
+ avg_abs_error_r > avg_abs_error_limit_ || |
+ avg_abs_error_g > avg_abs_error_limit_ || |
+ avg_abs_error_b > avg_abs_error_limit_ || |
+ max_abs_error_r > max_abs_error_limit_ || |
+ max_abs_error_g > max_abs_error_limit_ || |
+ max_abs_error_b > max_abs_error_limit_) { |
+ LOG(ERROR) << "Percentage of pixels with an error: " |
+ << error_pixels_percentage << "; " |
+ << "Percentage of pixels with errors not greater than " |
+ << small_error_threshold_ << ": " |
+ << small_error_pixels_percentage << "; " |
+ << "Average absolute error (excluding identical pixels): " |
+ << "R=" << avg_abs_error_r << " " |
+ << "G=" << avg_abs_error_g << " " |
+ << "B=" << avg_abs_error_b << "; " |
+ << "Largest absolute error: " |
+ << "R=" << max_abs_error_r << " " |
+ << "G=" << max_abs_error_g << " " |
+ << "B=" << max_abs_error_b; |
+ return false; |
+ } else { |
+ return true; |
+ } |
+} |
+ |
+} // namespace cc |