Home | History | Annotate | Download | only in test
      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