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')
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'], ))
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
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()
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()
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
def jpegimage(self, img_data, width, height): buf = IOClass(img_data) return Image.open(buf)
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
def save_image_to_fh(self, im): fh = IOClass() im.save(fh, 'PNG') fh.seek(0) return fh