Home | History | Annotate | Download | only in image_comparison
      1 # Copyright (c) 2014 The Chromium OS 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 import logging
      6 from autotest_lib.client.cros.video import method_logger
      7 from autotest_lib.client.cros.image_comparison import comparison_result
      8 
      9 # TODO (mussa): We will use data generated by running tests using this class.
     10 # If we can do with one comparer we may not need this class.
     11 
     12 class UploadOnFailComparer(object):
     13     """
     14     Compares a test image against a golden image.
     15 
     16     Uses a local comparer first to do the comparison, for every comparison
     17     that return fail, it uses remote comparer.
     18 
     19     """
     20 
     21 
     22     @method_logger.log
     23     def __init__(self, local_comparer, remote_comparer, threshold=0):
     24         """
     25         @param local_comparer: object impementing compare(), local comparer.
     26         @param remote_comparer: object implementing compare(), remote comparer.
     27         @param threshold: int, a value which the pixel difference between test
     28                           image and golden image has to exceed before the
     29                           remote comparer is used.
     30 
     31         """
     32         self.local_comparer = local_comparer
     33         self.remote_comparer = remote_comparer
     34         self.threshold = threshold
     35 
     36 
     37     def __enter__(self):
     38         return self
     39 
     40 
     41     @method_logger.log
     42     def compare(self, golden_image_path, test_image_path, box=None):
     43         """
     44         Compares a test image against a golden image using up to two comparers.
     45 
     46         If the local comparer reports a fail, use the remote comparer to
     47         compare the same images.
     48 
     49         E.g of use case: You have two comparers, one is local and another is
     50         web-based. Web-based comparer has the advantage of storing information
     51         you need to look at the results later.
     52         Local comparer is fast and reduces the load on the web-based comparer.
     53 
     54         Use local comparer as primary comparer and only invoke the web-based
     55         comparer on test images that differ from their golden counterparts.
     56 
     57         @param golden_image_path: path, complete path to the golden image.
     58         @param test_image_path: path, complete path  to the test image.
     59         @param box: int tuple, left, upper, right, lower pixel coordinates
     60                     defining a box region within which the comparison is made.
     61 
     62         @return: int, differing pixels as per double check comparer.
     63 
     64         """
     65         logging.debug('Using primary comparer..')
     66 
     67         with self.local_comparer:
     68             res = self.local_comparer.compare(golden_image_path,
     69                                                  test_image_path,
     70                                                  box)
     71             diffpx = res.diff_pixel_count
     72         logging.debug('Primary comparison complete. Diff pixels = %d', diffpx)
     73 
     74         diffpx2 = -1
     75         comp_res = res.comparison_url
     76 
     77         if (diffpx > self.threshold):
     78             logging.debug('Threshold diff pixels is %d', self.threshold)
     79             logging.debug('Diff pxls > threshold. Using remote comparer.')
     80 
     81             with self.remote_comparer:
     82                 res_remote = self.remote_comparer.compare(golden_image_path,
     83                                                           test_image_path,
     84                                                           box)
     85                 diffpx2 = res_remote.diff_pixel_count
     86 
     87             if not comp_res:
     88                 comp_res = res_remote.comparison_url
     89 
     90             logging.debug('Secondary comparison complete. Diff pixels = %d',
     91                           diffpx2)
     92 
     93         diffpx_return = diffpx2 if diffpx2 != -1 else diffpx
     94 
     95 
     96         return comparison_result.ComparisonResult(diffpx_return,
     97                                                   comp_res)
     98 
     99 
    100     def __exit__(self, exc_type, exc_val, exc_tb):
    101         pass
    102