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 5import heapq, logging 6 7from PIL import Image 8from PIL import ImageChops 9 10from autotest_lib.client.cros.image_comparison import comparison_result 11from autotest_lib.client.cros.video import method_logger 12 13 14""" 15 16*** Consider using PdiffImageComparer instead of this class *** 17 * This class uses pixel by pixel comparer while PdiffImageComparer encapsules 18 * the perceptualdiff tool available in ChromeOS 19 20""" 21 22 23class RGBImageComparer(object): 24 """ 25 Compares two RGB images using built-in python image library. 26 27 """ 28 29 30 def __init__(self, rgb_pixel_threshold): 31 self.pixel_threshold = rgb_pixel_threshold 32 33 34 @method_logger.log 35 def compare(self, golden_img_path, test_img_path, box=None): 36 """ 37 Compares a test image against a known golden image. 38 39 Both images must be RGB images. 40 41 @param golden_img_path: path, complete path to a golden image. 42 @param test_img_path: path, complete path to a test image. 43 @param box: int tuple, left, upper, right, lower pixel coordinates 44 defining a box region within which the comparison is made. 45 46 @return: int, number of pixels that are different. 47 48 """ 49 golden_image = Image.open(golden_img_path) 50 test_image = Image.open(test_img_path) 51 52 if golden_image.mode != 'RGB': 53 logging.debug('Golden image was not RGB. Converting to RGB.') 54 golden_image = golden_image.convert('RGB') 55 56 if test_image.mode != 'RGB': 57 logging.debug('Test image was not RGB. Converting to RGB.') 58 test_image = test_image.convert('RGB') 59 60 if box is not None: 61 golden_image = golden_image.crop(box) 62 test_image = test_image.crop(box) 63 64 diff_image = ImageChops.difference(golden_image, test_image) 65 maxcolors = diff_image.size[0] * diff_image.size[1] 66 colorstuples = diff_image.getcolors(maxcolors) 67 max_debug_count = 100 68 69 logging.debug("***ALL Color counts: %d", maxcolors) 70 logging.debug(heapq.nlargest(max_debug_count, colorstuples)) 71 72 # getcolors returns a list of (count, color) tuples where count is the 73 # number of times the corresponding color in the image. 74 75 above_thres_tuples = [t for t in colorstuples 76 if any(pixel > self.pixel_threshold 77 for pixel in t[1])] 78 79 logging.debug("Color counts above thres.: %d", len(above_thres_tuples)) 80 logging.debug(heapq.nlargest(max_debug_count, above_thres_tuples)) 81 82 diff_pixels = sum(t[0] for t in above_thres_tuples) 83 84 return comparison_result.ComparisonResult(diff_pixels, '') 85 86 87 def __enter__(self): 88 return self 89 90 91 def __exit__(self, exc_type, exc_val, exc_tb): 92 pass