def missing_RANDR(): if platform_is_osx(): return False if not display: return False disp = display.Display() return not disp.has_extension("RANDR")
def init(): global refimgpath if not refimgpath: d = tempfile.mkdtemp(prefix="fillscreen") d = Path(d) atexit.register(d.rmtree) refimgpath = d / "ref.png" if not platform_is_win(): # TODO: win image viewer im = generate_image() im.save(refimgpath) cmd = [ "pqiv", "--fullscreen", "--hide-info-box", "--disable-scaling", refimgpath, ] proc = EasyProcess(cmd).start() atexit.register(proc.stop) print(refimgpath) sleep(5) # TODO: check image displayed if not proc.is_alive(): raise FillscreenError("pqiv stopped: %s" % proc) # if the OS has color correction # then the screenshot has slighly different color than the original image # TODO: color correction: linux? win? if platform_is_win() or platform_is_osx(): refimgpath = refimgpath + ".pil.png" im = pyscreenshot.grab(backend="pil") im.save(refimgpath) log.debug("%s saved", refimgpath) return refimgpath
def grab(self, bbox=None): if platform_is_osx(): raise WxBackendError("osx not supported") import wx global app if not app: app = wx.App() screen = wx.ScreenDC() size = screen.GetSize() if wx.__version__ >= "4": bmp = wx.Bitmap(size[0], size[1]) else: bmp = wx.EmptyBitmap(size[0], size[1]) mem = wx.MemoryDC(bmp) mem.Blit(0, 0, size[0], size[1], screen, 0, 0) del mem if hasattr(bmp, "ConvertToImage"): myWxImage = bmp.ConvertToImage() else: myWxImage = wx.ImageFromBitmap(bmp) im = Image.new("RGB", (myWxImage.GetWidth(), myWxImage.GetHeight())) if hasattr(Image, "frombytes"): # for Pillow im.frombytes(to_bytes(myWxImage.GetData())) else: # for PIL im.fromstring(myWxImage.GetData()) if bbox: im = im.crop(bbox) return im
def display_size(): if platform_is_osx(): from Quartz import CGDisplayBounds from Quartz import CGMainDisplayID mainMonitor = CGDisplayBounds(CGMainDisplayID()) return int(mainMonitor.size.width), int(mainMonitor.size.height) if platform_is_win(): from win32api import GetSystemMetrics return int(GetSystemMetrics(0)), int(GetSystemMetrics(1)) if platform_is_linux(): # http://www.cyberciti.biz/faq/how-do-i-find-out-screen-resolution-of-my-linux-desktop/ # xdpyinfo | grep 'dimensions:' screen_width, screen_height = 0, 0 xdpyinfo = EasyProcess("xdpyinfo") xdpyinfo.enable_stdout_log = False if xdpyinfo.call().return_code != 0: raise ValueError("xdpyinfo error: %s" % xdpyinfo) for x in xdpyinfo.stdout.splitlines(): if "dimensions:" in x: screen_width, screen_height = map(int, x.strip().split()[1].split("x")) return screen_width, screen_height
def display_size(): if platform_is_osx(): return display_size_osx() if platform_is_win(): return display_size_win() if platform_is_linux(): return display_size_x()
def backends(childprocess): # the order is based on performance if platform_is_linux(): if use_x_display(): if childprocess: yield ScrotWrapper yield PilWrapper yield MssWrapper else: yield PilWrapper yield MssWrapper yield ScrotWrapper yield MaimWrapper yield ImagemagickWrapper yield Gdk3PixbufWrapper yield WxScreen for x in qt(): yield x yield GnomeDBusWrapper # on screen notification yield KwinDBusWrapper # flash effect yield GnomeScreenshotWrapper yield GrimWrapper elif platform_is_osx(): # first check for X if use_x_display(): pass else: # fast yield MssWrapper # latest version should work yield PilWrapper # alternatives for older pillow versions yield ScreencaptureWrapper yield MacQuartzWrapper # qt has some color difference # does not work: Gdk3, wx, Imagemagick elif platform_is_win(): # fast yield MssWrapper yield PilWrapper else: for x in backend_dict.values(): yield x
def grab(self, bbox=None): if platform_is_osx(): raise ImagemagickBackendError("osx not supported") command = [PROGRAM, "-silent", "-window", "root"] if bbox: pbox = "{}x{}+{}+{}".format(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1]) command += ["-crop", pbox] im = read_prog_img(command) return im
def grab(self, bbox=None): if not platform_is_osx(): raise ScreencaptureError("This backend runs only on Darwin") command = [PROGRAM, "-x"] if bbox: width = bbox[2] - bbox[0] height = bbox[3] - bbox[1] command += ["-R{},{},{},{}".format(bbox[0], bbox[1], width, height)] im = read_prog_img(command) return im
def grab(self, bbox=None): """Grabs an image directly to a buffer. :param bbox: Optional tuple or list containing (x1, y1, x2, y2) coordinates of sub-region to capture. :return: PIL RGB image :raises: ValueError, if image data does not have 3 channels (RGB), each with 8 bits. :rtype: Image """ if platform_is_osx(): raise Gdk3BackendError("osx not supported") import gi gi.require_version("Gdk", "3.0") # gi.require_version('GdkPixbuf', '2.0') from gi.repository import Gdk from gi.repository import GdkPixbuf # read_pixel_bytes: New in version 2.32. if GdkPixbuf.PIXBUF_MAJOR == 2: if GdkPixbuf.PIXBUF_MINOR < 32: raise ValueError( "GdkPixbuf min supported version: 2.32 current:" + GdkPixbuf.PIXBUF_VERSION ) w = Gdk.get_default_root_window() if bbox is not None: g = [bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]] else: g = w.get_geometry() pb = Gdk.pixbuf_get_from_window(w, *g) if not pb: raise Gdk3BackendError("empty buffer") if pb.get_bits_per_sample() != 8: raise Gdk3BackendError("Expected 8 bits per pixel.") elif pb.get_n_channels() != 3: raise Gdk3BackendError("Expected RGB image.") # Read the entire buffer into a python bytes object. # read_pixel_bytes: New in version 2.32. pixel_bytes = pb.read_pixel_bytes().get_data() # type: bytes width, height = g[2], g[3] # Probably for SSE alignment reasons, the pixbuf has extra data in each line. # The args after "raw" help handle this; see # http://effbot.org/imagingbook/decoder.htm#the-raw-decoder return Image.frombytes( "RGB", (width, height), pixel_bytes, "raw", "RGB", pb.get_rowstride(), 1 )
def grab(self, bbox=None): if platform_is_osx(): raise ImagemagickBackendError("osx not supported") # TODO # p = EasyProcess([PROGRAM, "-version"]) # p.enable_stdout_log = False # p.enable_stderr_log = False # p.call() command = [PROGRAM, "-silent", "-window", "root"] if bbox: pbox = "{}x{}+{}+{}".format(bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1]) command += ["-crop", pbox] im = read_prog_img(command) return im
def grab(self, bbox=None): if not platform_is_osx(): raise ScreencaptureError("This backend runs only on Darwin") # p = EasyProcess([PROGRAM, "-help"]) # p.enable_stdout_log = False # p.enable_stderr_log = False # p.call() command = [PROGRAM, "-x"] if bbox: width = bbox[2] - bbox[0] height = bbox[3] - bbox[1] command += [ "-R{},{},{},{}".format(bbox[0], bbox[1], width, height) ] im = read_prog_img(command) return im
def check_ref(backend, bbox, childprocess, refimgpath): img_ref = Image.open(refimgpath) logging.debug("ref full getextrema: %s", img_ref.getextrema()) if bbox: img_ref = img_ref.crop(bbox) im = pyscreenshot.grab(bbox=bbox, backend=backend, childprocess=childprocess) img_ref = img_ref.convert("RGB") logging.debug("ref getextrema: %s", img_ref.getextrema()) im = im.convert("RGB") logging.debug("shot getextrema: %s", im.getextrema()) eq_("RGB", img_ref.mode) eq_("RGB", im.mode) img_debug(img_ref, "ref" + str(bbox)) img_debug(im, str(backend) + str(bbox)) img_diff = ImageChops.difference(img_ref, im) ex = img_diff.getextrema() logging.debug("diff getextrema: %s", ex) diff_bbox = img_diff.getbbox() if diff_bbox: img_debug(img_diff, "img_diff" + str(diff_bbox)) if (platform_is_osx() and backend and backend in ["qtpy", "pyqt", "pyqt5", "pyside", "pyside2"]): # TODO: qt color problem on osx color_diff_max = max([b for (_, b) in ex]) ok_(color_diff_max < 70) else: eq_( diff_bbox, None, "different image data %s bbox=%s extrema:%s diff_bbox=%s" % (backend, bbox, ex, diff_bbox), )
def init(): global refimgpath if not refimgpath: d = tempfile.mkdtemp(prefix="fillscreen") atexit.register(lambda: rmtree(d)) refimgpath = join(d, "ref.png") im = generate_image() im.save(refimgpath) if platform_is_win(): cmd = [ "C:\\Program Files (x86)\\FastStone Image Viewer\\FSViewer.exe", refimgpath, ] else: cmd = [ "pqiv", "--fullscreen", "--hide-info-box", "--disable-scaling", refimgpath, ] proc = EasyProcess(cmd).start() atexit.register(proc.stop) print(refimgpath) sleep(5) # wait for image displayed if not proc.is_alive(): raise FillscreenError("pqiv stopped: %s" % proc) # if the OS has color correction # then the screenshot has slighly different color than the original image if platform_is_win() or platform_is_osx(): refimgpath = refimgpath + ".pil.png" im = pyscreenshot.grab(backend="pil") im.save(refimgpath) log.debug("%s saved", refimgpath) return refimgpath
from pyscreenshot.util import platform_is_osx from bt import backend_to_check, check_import # qt color problem on osx if not platform_is_osx(): if check_import("PySide"): def test_pyside(): backend_to_check("pyside")
try: from Xlib import display except ImportError: display = None # https://github.com/python-xlib/python-xlib/blob/master/examples/xrandr.py#L44 def missing_RANDR(): if display: return False disp = display.Display() return not disp.has_extension("RANDR") ok = False if not six.PY2 and check_import("mss"): if platform_is_osx() and not use_x_display(): ok = True if platform_is_linux() and use_x_display(): ok = True if platform_is_win(): ok = True if ok: def test_mss(): if missing_RANDR(): try: backend_to_check("mss") except FailedBackendError: pass else:
from bt import backend_to_check from pyscreenshot.util import platform_is_osx if platform_is_osx(): def test_mac_screencapture(): backend_to_check("mac_screencapture")
from bt import backend_to_check, check_import from pyscreenshot.util import platform_is_osx if not platform_is_osx() and check_import("wx"): def test_wx(): backend_to_check("wx")