Код
#!/usr/bin/python
import warnings
import ctypes
import numpy as np
from Xlib import X, display
from xpresser.image import Image
from autox import AutoX
from pyxlib_ctypes import XGetImage, Display, Drawable, ZPixmap, XOpenDisplay, XDefaultScreen, XRootWindow
# xlib is using a deprecated method from struct
warnings.filterwarnings("ignore", ".*struct integer overflow.*")
_ax = AutoX()
def click(x, y):
_ax.move_pointer(x, y)
_ax.press_button(1)
_ax.release_button(1)
def hover(x, y):
_ax.move_pointer(x, y)
def type(string):
_ax.send_text(string)
_disp = XOpenDisplay(None)
_scr = XDefaultScreen(_disp)
_root_win = XRootWindow(_disp, _scr)
class ScreenGrabber(object):
def __init__(self):
self.display = display.Display()
self.root = self.display.get_input_focus().focus.query_tree().root
if self.root == 0:
self.root = self.display.get_input_focus()
self.width = self.root.get_geometry().width
self.height = self.root.get_geometry().height
def fast(self, x=0, y=0, width=None, height=None):
if width is None:
width = self.width
if height is None:
height = self.height
ximg_pointer = XGetImage(_disp, _root_win, x, y, width, height, ~0, ZPixmap)
ximg = ximg_pointer.contents
width, height = ximg.width, ximg.height
size = width * height * 4
data = ctypes.string_at(ximg.data, size)
# xpresser.Image either requires a file or a numpy ndarray
array = np.ndarray( # create multi-dimensional array
shape=(height*width,4), dtype=np.uint8, # with 4 elements (b, g, r, x) each
buffer=data)
array = np.delete(array, np.s_[3:4], axis=1).T # remove alpha channel and transpose (rols to cols)
array = np.column_stack(
(array[2], array[1], array[0]) # swap columns bgr -> rgb
).reshape(height , width, 3) # reshape to image geometry
return Image("screenshot", array=array, width=width, height=height)
def slow(self, x=0, y=0, width=None, height=None):
if width is None:
width = self.width
if height is None:
height = self.height
# Grabbing a complete screen is slow
##data = self.root.get_image(x, y, width, height, X.ZPixmap, ~0).data
# Therefore each line will be grabbed separately
# (which is a lot faster for some unknown reasons)
get_image = self.root.get_image # this is to speed-up name look-ups
data = "".join((get_image(x, yi, width, 1, X.ZPixmap, ~0).data for yi in xrange(y, y+height)))
# xpresser.Image either requires a file or a numpy ndarray
array = np.ndarray( # create multi-dimensional array
shape=(height*width,4), dtype=np.uint8, # with 4 elements (b, g, r, x) each
buffer=data)
array = np.delete(array, np.s_[3:4], axis=1).T # remove alpha channel and transpose (rols to cols)
array = np.column_stack(
(array[2], array[1], array[0]) # swap columns bgr -> rgb
).reshape(height , width, 3) # reshape to image geometry
## Show with:
#import PIL
#img = PIL.Image.fromstring("RGB", (width,height), array.tostring(), "raw")
#img.show()
return Image("screenshot", array=array, width=width, height=height)
__call__ = fast
take_screenshot = ScreenGrabber()