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