示例#1
0
 def get_screenshot_as_image(self):
     """
     Returns a screenshot of the current page as an RGB
     `PIL image <http://www.pythonware.com/library/pil/handbook/image.htm>`_.
     """
     fh = IOClass(base64.b64decode(self.get_screenshot_as_base64().encode('ascii')))
     return Image.open(fh).convert('RGB')
示例#2
0
文件: driver.py 项目: jmbowman/needle
    def get_screenshot(self):
        """
        Returns a screenshot of this element as a PIL image.
        """
        d = self.get_dimensions()

        # Cast values to int in order for _ImageCrop not to break
        d['left'] = int(d['left'])
        d['top'] = int(d['top'])
        d['width'] = int(d['width'])
        d['height'] = int(d['height'])

        try:
            # For selenium >= 2.46.1, W3C WebDriver spec drivers (like geckodriver)
            fh = IOClass(self.screenshot_as_png)
            image = Image.open(fh).convert('RGB')
            # Make sure it isn't actually a full-page screenshot (PhantomJS)
            if image.size == (d['width'], d['height']):
                return image
        except (AttributeError, WebDriverException):
            # Fall back to cropping a full page screenshot
            image = self._parent.get_screenshot_as_image()

        return image.crop((
            d['left'],
            d['top'],
            d['left'] + d['width'],
            d['top'] + d['height'],
        ))
示例#3
0
    def get_screenshot(self, element=None):
        """Returns screenshot image

        :param WebElement element: Crop image to element (Optional)
        :return:
        """

        stream = IOClass(
            base64.b64decode(
                self.driver.get_screenshot_as_base64().encode('ascii')))
        image = Image.open(stream).convert('RGB')

        if isinstance(element, WebElement):

            window_size = self._get_window_size()

            image_size = image.size

            # Get dimensions of element
            dimensions = self._get_element_dimensions(element)

            if not image_size == (dimensions['width'], dimensions['height']):

                ratio = self._get_ratio(image_size, window_size)

                return image.crop([
                    point * ratio for point in self._get_element_rect(element)
                ])

        return image
示例#4
0
 def save(self):
     """
     Save the image to the cache if provided and not cached yet.
     """
     if self.cache and not self.is_cached:
         image_str = IOClass()
         # not much other supports than png, yet works
         self.pil.save(image_str, 'png')
         self.cache.set(self.cached_name, image_str.getvalue())
         image_str.close()
示例#5
0
 def render(self):
     """
     Renders the file content
     """
     if self.is_cached:
         return self.cache.get(self.cached_name)
     else:
         image_str = IOClass()
         # not much other supports than png, yet works
         self.pil.save(image_str, 'png')
         return image_str.getvalue()
示例#6
0
 def paint_image(self, coding, img_data, x, y, width, height, rowstride,
                 options, callbacks):
     """ can be called from any thread """
     assert coding in ENCODINGS
     if use_PIL:
         #try PIL first since it doesn't need the UI thread until the actual do_paint_rgb24 call
         buf = IOClass(img_data)
         img = Image.open(buf)
         if img.mode == "RGB":
             raw_data = img.tostring("raw", "RGB")
             #PIL flattens the data to a continuous straightforward RGB format:
             rowstride = width * 3
             img_data = self.process_delta(raw_data, width, height,
                                           rowstride, options)
             gobject.idle_add(self.do_paint_rgb24, img_data, x, y, width,
                              height, rowstride, options, callbacks)
             return False
     #gdk needs UI thread:
     gobject.idle_add(self.paint_pixbuf_gdk, coding, img_data, x, y, width,
                      height, options, callbacks)
     return False
示例#7
0
 def jpegimage(self, img_data, width, height):
     buf = IOClass(img_data)
     return Image.open(buf)
示例#8
0
    def get_screenshot(self, exclude=None):
        """
        Returns a screenshot of this element as a PIL image.
        :param exclude: list of Selectors of the elements to be excluded for image comparison
        (A mask is applied to the elements)
        """
        include_dimensions = self.get_dimensions()
        try:
            if exclude is not None or self.driver.capabilities.get(
                    'deviceName') is not None:
                self.driver.execute_script("window.scrollTo(0, 0)")
                stream = IOClass(
                    base64.b64decode(
                        self.driver.get_screenshot_as_base64().encode(
                            'ascii')))
                image = Image.open(stream).convert('RGB')
            else:
                fh = IOClass(self.screenshot_as_png)
                image = Image.open(fh).convert('RGB')
        except (AttributeError, WebDriverException):
            # Fall back to cropping a full page screenshot
            image = self._parent.get_screenshot_as_image()

        # screen height includes the status bar and navigation bar in mobile devices
        screen_height = int(
            self.driver.execute_script("return screen.height;"))
        # screen width includes horizontal scroll bar in mobile devices
        screen_width = int(self.driver.execute_script("return screen.width;"))
        window_size = screen_width, screen_height
        if self.driver.capabilities.get('deviceName') is not None:
            inner_height = int(
                self.driver.execute_script(
                    "return Math.max(document.documentElement.clientHeight, window.innerHeight || 0);"
                ))
            if self.driver.capabilities.get('platformName') == 'Android':
                """ Screenshot on Android Chrome doesn't contain the status bar, however it looks like the viewport height 
                changes when the status bar is hidden. Adding status bar height to the screen inner height equal the new
                viewport height"""
                window_size = screen_width, inner_height + self.ANDROID_STATUS_BAR_HEIGHT

            image = image.resize(window_size, Image.ANTIALIAS)
            """ Screenshot on iOS Safari includes its status bar (top) and navigation bar (bottom). It causes the 
            Y coordinate to be incorrect since element position relative to the viewport. The workaround for now is to 
            crop off the status bar"""
            if self.driver.capabilities.get('platformName') == 'iOS':
                include_dimensions = self.get_dimensions()
                image = image.crop((0, self.IOS_STATUS_BAR_HEIGHT,
                                    screen_width, screen_height))
        image_size = image.size
        if image_size[0] * image_size[1] >= window_size[0] * window_size[0]:
            window_size = image_size
        ratio = self._get_ratio(image_size, window_size)
        if isinstance(exclude, (list, tuple)) and exclude:
            elements = [
                self.driver.find_element(*element) for element in exclude
            ]
            for element in elements:
                dimensions = element.get_dimensions()
                canvas = ImageDraw.Draw(image)
                canvas.rectangle([
                    point * ratio
                    for point in (dimensions['left'], dimensions['top'],
                                  (dimensions['left'] + dimensions['width']),
                                  (dimensions['top'] + dimensions['height']))
                ],
                                 fill=ImageColor.getrgb('black'))
        if include_dimensions['height'] > image_size[1] or include_dimensions[
                'width'] > image_size[0]:
            logging.info(
                f"The element dimensions ({include_dimensions['width']}, {include_dimensions['height']}) "
                f"are larger than the image size ({image_size[0]}, {image_size[1]}). Resetting the element size to "
                f"match with the image size.")
            include_dimensions['height'] = image_size[1] if include_dimensions[
                'height'] > image_size[1] else include_dimensions['height']
            include_dimensions['width'] = image_size[0] if include_dimensions[
                'width'] > image_size[0] else include_dimensions['width']

        if not image_size == (include_dimensions['width'],
                              include_dimensions['height']):
            return image.crop([
                point * ratio for point in (include_dimensions['left'],
                                            include_dimensions['top'],
                                            (include_dimensions['left'] +
                                             include_dimensions['width']),
                                            (include_dimensions['top'] +
                                             include_dimensions['height']))
            ])
        return image
示例#9
0
 def save_image_to_fh(self, im):
     fh = IOClass()
     im.save(fh, 'PNG')
     fh.seek(0)
     return fh