1# Copyright 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"""Classes to do screen capture.""" 6 7import logging 8 9from PIL import Image 10 11from autotest_lib.client.cros.multimedia import image_generator 12 13 14def _unlevel(p): 15 """Unlevel a color value from TV level back to PC level 16 17 @param p: The color value in one character byte 18 19 @return: The color value in integer in PC level 20 """ 21 # TV level: 16~236; PC level: 0~255 22 p = (p - 126) * 128 // 110 + 128 23 if p < 0: 24 p = 0 25 elif p > 255: 26 p = 255 27 return p 28 29 30class CommonChameleonScreenCapturer(object): 31 """A class to capture the screen on Chameleon. 32 33 Calling its member method capture() captures the screen. 34 35 """ 36 TAG = 'Chameleon' 37 38 def __init__(self, chameleon_port): 39 """Initializes the CommonChameleonScreenCapturer objects.""" 40 self._chameleon_port = chameleon_port 41 42 43 def capture(self): 44 """Captures the screen. 45 46 @return An Image object. 47 """ 48 logging.info('Capturing the screen on Chameleon...') 49 image = self._chameleon_port.capture_screen() 50 51 # unleveling from TV level [16, 235] 52 pmin, pmax = image_generator.ImageGenerator.get_extrema(image) 53 if pmin > 10 and pmax < 240: 54 logging.info(' (TV level: %d %d)', pmin, pmax) 55 image = Image.eval(image, _unlevel) 56 return image 57 58 59class VgaChameleonScreenCapturer(object): 60 """A class to capture the screen on a VGA port of Chameleon. 61 62 Calling its member method capture() captures the screen. 63 64 """ 65 TAG = 'Chameleon' 66 67 def __init__(self, chameleon_port): 68 """Initializes the VgaChameleonScreenCapturer objects.""" 69 self._chameleon_port = chameleon_port 70 71 72 def capture(self): 73 """Captures the screen. 74 75 @return An Image object. 76 """ 77 logging.info('Capturing the screen on a VGA port of Chameleon...') 78 image = self._chameleon_port.capture_screen() 79 80 # Find the box containing white points on its boundary. 81 boundary = image.convert('L').point( 82 lambda x: 255 if x >= 220 else 0).getbbox() 83 logging.info('Boundary: %r', boundary) 84 image = image.crop(boundary) 85 return image 86 87 88class CrosExternalScreenCapturer(object): 89 """A class to capture the external screen on Chrome OS. 90 91 Calling its member method capture() captures the screen. 92 93 """ 94 TAG = 'CrOS-Ext' 95 96 def __init__(self, display_facade): 97 """Initializes the CrosExternalScreenCapturer objects.""" 98 self._display_facade = display_facade 99 100 101 def capture(self): 102 """Captures the screen. 103 104 @return An Image object. 105 """ 106 logging.info('Capturing the external screen on CrOS...') 107 return self._display_facade.capture_external_screen() 108 109 110class CrosInternalScreenCapturer(object): 111 """A class to capture the internal screen on Chrome OS. 112 113 Calling its member method capture() captures the screen. 114 115 """ 116 TAG = 'CrOS-Int' 117 118 def __init__(self, display_facade): 119 """Initializes the CrosInternalScreenCapturer objects.""" 120 self._display_facade = display_facade 121 122 123 def capture(self): 124 """Captures the screen. 125 126 @return An Image object. 127 """ 128 logging.info('Capturing the internal screen on CrOS...') 129 return self._display_facade.capture_internal_screen() 130 131 132class CrosCalibrationImageCapturer(object): 133 """A class to capture the calibration image on Chrome OS. 134 135 Calling its member method capture() captures the image. 136 137 """ 138 TAG = 'Calibration' 139 140 def __init__(self, display_facade): 141 """Initializes the CrosCalibrationImageCapturer objects.""" 142 self._display_facade = display_facade 143 144 145 def capture(self): 146 """Captures the screen. 147 148 @return An Image object. 149 """ 150 logging.info('Capturing the calibration image on CrOS...') 151 return self._display_facade.capture_calibration_image() 152