Python screenshot library, replacement for the Pillow ImageGrab module on Linux.

Overview

tldr: Use Pillow

The pyscreenshot module is obsolete in most cases. It was created because PIL ImageGrab module worked on Windows only, but now Linux and macOS are also supported by Pillow. There are some features in pyscreenshot which can be useful in special cases: flexible backends, Wayland support, sometimes better performance, optional subprocessing.

The module can be used to copy the contents of the screen to a Pillow image memory using various back-ends. Replacement for the ImageGrab Module.

For handling image memory (e.g. saving to file, converting,..) please read Pillow documentation.

Links:

Build Status

Goal: Pyscreenshot tries to allow to take screenshots without installing 3rd party libraries. It is cross-platform. It is only a pure Python wrapper, a thin layer over existing back-ends. Its strategy should work on most Linux distributions: a lot of back-ends are wrapped, if at least one exists then it works, if not then one back-end should be installed.

Features:

Known problems:

Installation:

$ python3 -m pip install Pillow pyscreenshot

Examples

# pyscreenshot/examples/grabfullscreen.py

"Grab the whole screen"
import pyscreenshot as ImageGrab

# grab fullscreen
im = ImageGrab.grab()

# save image file
im.save("fullscreen.png")
# pyscreenshot/examples/grabbox.py

"Grab the part of the screen"
import pyscreenshot as ImageGrab

# part of the screen
im = ImageGrab.grab(bbox=(10, 10, 510, 510))  # X1,Y1,X2,Y2

# save image file
im.save("box.png")
# pyscreenshot/examples/virtdisp.py

"Create screenshot of xmessage with Xvfb"
from time import sleep

from easyprocess import EasyProcess
from pyvirtualdisplay import Display

import pyscreenshot as ImageGrab

with Display(size=(100, 60)) as disp:  # start Xvfb display
    # display is available
    with EasyProcess(["xmessage", "hello"]):  # start xmessage
        sleep(1)  # wait for diplaying window
        img = ImageGrab.grab()
img.save("xmessage.png")

Image:

Performance

The performance can be checked with pyscreenshot.check.speedtest module. Backends are started in a subprocess with default (safest) settings which is necessary to isolate them from the main process and from each other. Disabling this option makes performance much better, but it may cause problems in some cases.

Test on Ubuntu 20.04 X11

Versions:

$ python3 -m pyscreenshot.check.versions
python               3.8.5
pyscreenshot         2.3
pil                  8.0.1
mss                  6.1.0
scrot                1.2
grim                 ?.?
maim                 5.5.3
imagemagick          6.9.10
pyqt5                5.14.1
pyqt                 
pyside2              5.14.0
pyside               
wx                   4.0.7
pygdk3               3.36.0
mac_screencapture    
mac_quartz           
gnome_dbus           ?.?
gnome-screenshot     3.36.0
kwin_dbus            ?.?
$ python3 -m pyscreenshot.check.speedtest

n=10
------------------------------------------------------
default             	1    sec	(  101 ms per call)
pil                 	1.7  sec	(  166 ms per call)
mss                 	1.9  sec	(  191 ms per call)
scrot               	0.97 sec	(   97 ms per call)
grim                	
maim                	1.4  sec	(  144 ms per call)
imagemagick         	2.4  sec	(  235 ms per call)
pyqt5               	4.3  sec	(  429 ms per call)
pyqt                	
pyside2             	4.2  sec	(  423 ms per call)
pyside              	
wx                  	4.1  sec	(  412 ms per call)
pygdk3              	2    sec	(  204 ms per call)
mac_screencapture   	
mac_quartz          	
gnome_dbus          	1.4  sec	(  144 ms per call)
gnome-screenshot    	3.8  sec	(  381 ms per call)
kwin_dbus           	
$ python3 -m pyscreenshot.check.speedtest --childprocess 0

n=10
------------------------------------------------------
default             	0.11 sec	(   10 ms per call)
pil                 	0.09 sec	(    8 ms per call)
mss                 	0.15 sec	(   15 ms per call)
scrot               	0.95 sec	(   95 ms per call)
grim                	
maim                	1.5  sec	(  145 ms per call)
imagemagick         	2.4  sec	(  235 ms per call)
pyqt5               	1.1  sec	(  114 ms per call)
pyqt                	
pyside2             	1.2  sec	(  118 ms per call)
pyside              	
wx                  	0.43 sec	(   43 ms per call)
pygdk3              	0.16 sec	(   15 ms per call)
mac_screencapture   	
mac_quartz          	
gnome_dbus          	1.5  sec	(  147 ms per call)
gnome-screenshot    	3.8  sec	(  383 ms per call)
kwin_dbus           	

You can force a backend:

import pyscreenshot as ImageGrab
im = ImageGrab.grab(backend="scrot")

You can force if subprocess is applied, setting it to False together with mss gives the best performance in most cases:

# best performance
import pyscreenshot as ImageGrab
im = ImageGrab.grab(backend="mss", childprocess=False)

Wayland

Wayland is supported with two setups:

  1. using D-Bus on GNOME or KDE. Python 3 only.
  2. using Grim on any Wayland compositor with wlr-screencopy-unstable-v1 support. (GNOME:no, KDE:no, Sway:yes)

If both Wayland and X are available then Wayland is preferred because Xwayland can not be used for screenshot.
Rules for decision:

  1. use X if DISPLAY variable exists and XDG_SESSION_TYPE variable != "wayland"
  2. use Wayland if 1. is not successful

Dependencies

Only pure python modules are used:

  1. EasyProcess for calling programs
  2. entrypoint2 for generating command line interface
  3. MSS backend is added because it is very fast and pure and multiplatform
  4. jeepney for D-Bus calls

Hierarchy

Alt text

Comments
  • pyscreenshot.grab() on Mac, box is additive and not absolute.

    pyscreenshot.grab() on Mac, box is additive and not absolute.

    On linux, the bounding box is absolute, i.e., bounding box (5, 5, 10, 10), it means: point (5,5) and point (10,10). However, on Mac, the bounding box is additive, i.e., it means point (5,5) and point (15, 15). Ugly fix could be:

        def grab_to_file(self, filename, bbox=None, dpi=72):
            # FIXME: Should query dpi from somewhere, e.g for retina displays
            region = self.CG.CGRectMake(bbox[1], bbox[2], bbox[3]-bbox[1], bbox[4]-bbox[2]) if bbox else self.CG.CGRectInfinite
    
            # Create screenshot as CGImage
            image = self.CG.CGWindowListCreateImage(region,
                                                    self.CG.kCGWindowListOptionOnScreenOnly, self.CG.kCGNullWindowID,
    self.CG.kCGWindowImageDefault)
    
    opened by J-Moravec 15
  • Pillow Installed But Not Working

    Pillow Installed But Not Working

    Installed Pillow-2.7 and pyscreenshot-0.3.3 on Python 2.7.8 32-bit on Windows 7 64-bit. pyscreenshot.grab() continued to generate error:

    import pyscreenshot as pss pss.grab() Traceback (most recent call last): File "", line 1, in File "C:\Python27\ArcGIS10.3\lib\site-packages\pyscreenshot-0.3.3-py2.7.egg\pyscreenshot__init__.py", line 71, in grab return grab(to_file=False, childprocess=childprocess, backend=backend, bbox=bbox) File "C:\Python27\ArcGIS10.3\lib\site-packages\pyscreenshot-0.3.3-py2.7.egg\pyscreenshot__init_.py", line 51, in _grab backend_obj = _get_loader().selected() File "C:\Python27\ArcGIS10.3\lib\site-packages\pyscreenshot-0.3.3-py2.7.egg\pyscreenshot\loader.py", line 75, in selected self.raise_exc() File "C:\Python27\ArcGIS10.3\lib\site-packages\pyscreenshot-0.3.3-py2.7.egg\pyscreenshot\loader.py", line 83, in raise_exc raise FailedBackendError(message) pyscreenshot.loader.FailedBackendError: Install at least one backend!

    Updating line 14 of pil.py to: from PIL import ImageGrab

    Seemed to resolve the error. That said, not sure if that will cause issues in other places.

    opened by bixb0012 10
  • Import Error

    Import Error

    While easy_install it, I get this:

    File "/tmp/easy_install-32xFOz/pyscreenshot-0.1.0/pyscreenshot/init.py", line 1, in # ImportError: No module named path

    Fixed 
    opened by keul 9
  • PyScreenshot: Segmentation fault (core dumped)

    PyScreenshot: Segmentation fault (core dumped)

    The first screenshot taken with PyScreenshot is fine: however, after I have taken one screenshot, when I take another, the application crashes. In PyCharm, it finishes with exit code 139. In the terminal, the output is 'Segmentation fault (core dumped)' and the application stops executing.

    untitled

    opened by lukep4 7
  • Exclude fix import

    Exclude fix import

    Allows Python3 use - see #17. Note this requires all imports to be absolute -- see https://wiki.python.org/moin/PortingPythonToPy3k#relative-imports.

    opened by kevinmickey 7
  • pygdk3 backend, using Gdk 3.0+, compatible with Python3 and pretty fa…

    pygdk3 backend, using Gdk 3.0+, compatible with Python3 and pretty fa…

    …st (~70ms for 4K screenshot)

    Fixes / avoids https://github.com/ponty/pyscreenshot/issues/43

    N.B. you must use childprocess=False to get good performance!! Unfortunately default Python inter-thread communication/forking/etc. is painfully slow. Compare:

    In [5]: %time pyscreenshot.grab(backend='pygdk3')
    CPU times: user 6.38 ms, sys: 0 ns, total: 6.38 ms
    Wall time: 397 ms
    Out[5]: <PIL.PngImagePlugin.PngImageFile image mode=RGB size=3840x2160 at 0x7F9721DA4908>
    
    In [7]: %time pyscreenshot.grab(backend='pygdk3', childprocess=False)
    CPU times: user 59.1 ms, sys: 27.9 ms, total: 87 ms
    Wall time: 102 ms
    Out[7]: <PIL.Image.Image image mode=RGB size=3840x2160 at 0x7F970E57FF28>
    
    In [8]: %time pyscreenshot.grab(backend='pygdk3', childprocess=False)
    CPU times: user 36.7 ms, sys: 12.1 ms, total: 48.8 ms
    Wall time: 67.9 ms
    Out[8]: <PIL.Image.Image image mode=RGB size=3840x2160 at 0x7F970E5841D0>
    
    In [9]: %time pyscreenshot.grab(backend='pygdk3', childprocess=False)
    CPU times: user 26.9 ms, sys: 19.4 ms, total: 46.2 ms
    Wall time: 65.3 ms
    Out[9]: <PIL.Image.Image image mode=RGB size=3840x2160 at 0x7F970E584550>
    

    Backend speedtest (which does not use childprocess=False) results:

    n=10                                                                                             
    ------------------------------------------------------                     
    pygdk3                  3.8  sec        (  383 ms per call)
    pyqt5                   7.4  sec        (  741 ms per call)
    imagemagick             11   sec        ( 1062 ms per call)
    gnome-screenshot        8.8  sec        (  883 ms per call)
    

    but with childprocess=False it is an order of magnitude faster than other backends ^_^. Sorry I don't have scrot/pyside/pyqt/wx/pil backends installed to compare.

    opened by gatoatigrado 6
  • Why so slow?

    Why so slow?

    Is there any reason for the backend code to be structured around writing to files? And also on a separate process? For backends that don't need it (gtk, qt, ...?), it seems performance would be hundreds/thousands of times better if operations are done in memory.

    opened by goncalopp 6
  • Full screen not being captured

    Full screen not being captured

    I am running Windows 10 and Python 3.4.3.

    Whenever I run your full screen example:

    $ python -m pyscreenshot.examples.showgrabfullscreen
    

    I only get a partial top-left of my screen:

    pyscreenshot

    If I force the size of my screen with grab(bbox=(0,0,3200,1800)) I get the same image and pure black filling out the rest of the area:

    forced

    opened by gnychis 6
  • ImageMagick backend

    ImageMagick backend

    Are you sure that the implementation of bbox is correct in this case,

    (bbox[2] - bbox[0], bbox[3] - bbox[1], bbox[0], bbox[1])
    

    Here you are calculating the width and height from points but the other examples are with X,Y, Width, Height

    So using this you will have different behaviors from the different plugins!

    Does it make sense?

    I suggest to change the plugin as

    (bbox[2] , bbox[3], bbox[0], bbox[1])
    

    Thanks

    opened by gastonrobledo-santex 6
  • Any thoughts about captureing multiple screens?

    Any thoughts about captureing multiple screens?

    Here is the situation, I got more than one screen connected to my computer. And I can not capture the second screen with pyscreenshot. Tried to use coordinates outside the first screen, but only get blackout where I thought there will be the second screen's picture.

    opened by Nriver 5
  • scrot 1.1.1 causing OSError: cannot identify image file

    scrot 1.1.1 causing OSError: cannot identify image file

    System: Pop!_OS v19.10 python3.7

    Using pyscreenshot.grab() causes an OSError using scrot v1.1.1 on my system as it tries to open a file called /tmp/pyscreenshot_scrot_alnh_dsl.png but in the system its called /tmp/pyscreenshot_scrot_alnh_dsl_000.png. This does not occur when using grab(backend=gnome-screenshot) and it does not crash using scrot 0.8 compiled from source.

    I have worked around this issue by adding filename = "_000.".join(filename.split(".")) on line 24 in pyscreenshot/plugins/scrot.py but its not really pretty and one of the created files are not removed from /tmp. It looks like some naming is going very wrong somewhere?

    Full traceback:

      File "/home/elias-eriksson/Dev/Project/main2.py", line 7, in <module>
        a = grab(backend="scrot")
      File "/home/elias-eriksson/Dev/Project/venv/lib/python3.7/site-packages/pyscreenshot/__init__.py", line 67, in grab
        to_file=False, childprocess=childprocess, backend=backend, bbox=bbox)
      File "/home/elias-eriksson/Dev/Project/venv/lib/python3.7/site-packages/pyscreenshot/__init__.py", line 46, in _grab
        _grab_simple, imcodec.codec, to_file, backend, bbox, filename)
      File "/home/elias-eriksson/Dev/Project/venv/lib/python3.7/site-packages/pyscreenshot/procutil.py", line 37, in run_in_childprocess
        raise e
    OSError: cannot identify image file '/tmp/pyscreenshot_scrot_alnh_dsl.png'
    
    opened by EliasEriksson 4
  • "All backends failed" on GNOME 42

    We can not use pyscreenshot on GNOME 42, I believe because the lack of the gnome-screenshot app. Do you know some command line we can use instead? If so maybe I can PR some solution. Thanks!

    image

    opened by jonata 0
  • docs: Fix a few typos

    docs: Fix a few typos

    There are small typos in:

    • README.md
    • pyscreenshot/examples/virtdisp.py
    • pyscreenshot/plugins/mac_screencapture.py
    • tests/fillscreen.py

    Fixes:

    • Should read displaying rather than diplaying.
    • Should read slightly rather than slighly.
    • Should read screenshots rather than screneshots.

    Semi-automated pull request generated by https://github.com/timgates42/meticulous/blob/master/docs/NOTE.md

    opened by timgates42 0
  • No module named 'PIL

    No module named 'PIL

    Hello,

    There is some problem after type: import pyscreenshot as ImageGrab

    error message: No module named 'PIL'

    So i have to do: pip install Pillow

    After i looked it is: init.py -> 4 line: from pyscreenshot.childproc import childprocess_backend_version childproc.py -> 6 line: from pyscreenshot.imcodec import codec imcodec.py -> 3 line: from PIL import Image

    So I think it needs to be added in: setup.py, install_requires

    opened by koroner1 1
  • Screen capture in MacOS

    Screen capture in MacOS

    See https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos

    A Mac-specific code, maybe in PIL or the Python Launcher itself, needs to be added to allow the app to request the screen capture permission BEFORE the code will work on Apple MacOS Catalina or later. As none of the other solutions work on all platforms (Linux, Win10, MacOS), it would be nice if you could get this fix pushed through (or integrated into your code if possible).

    opened by RandyHarr 1
  • how to save clipboard image as file

    how to save clipboard image as file

    I want to convert clipboard image content into an image

    I tried

    from PIL import ImageGrab
    im = ImageGrab.grabclipboard() is macOS and Windows only
    im.save(filename)
    

    it says ImageGrab.grabclipboard() is macOS and Windows only

    I think using this library its can be possible

    opened by sant527 1
Owner
null
List of Linux Tools I put on almost every linux / Debian host

Linux-Tools List of Linux Tools I put on almost every Linux / Debian host Installed: geany --> GUI editor/ notepad++ like chkservice --> TUI Linux ser

Stew Alexander 20 Jan 2, 2023
Organize seu linux - organize your linux

OrganizeLinux Organize seu linux - organize your linux Organize seu linux Uma forma rápida de separar arquivos dispersos em pastas. formatos a serem c

Marcus Vinícius Ribeiro Andrade 1 Nov 30, 2021
pyshell is a Linux subprocess module

pyshell A Linux subprocess module, An easier way to interact with the Linux shell pyshell should be cross platform but has only been tested with linux

null 4 Mar 2, 2022
Module for remote in-memory Python package/module loading through HTTP/S

httpimport Python's missing feature! The feature has been suggested in Python Mailing List Remote, in-memory Python package/module importing through H

John Torakis 220 Dec 17, 2022
Python3 Interface to numa Linux library

py-libnuma is python3 interface to numa Linux library so that you can set task affinity and memory affinity in python level for your process which can help you to improve your code's performence.

Dalong 13 Nov 10, 2022
PyPIContents is an application that generates a Module Index from the Python Package Index (PyPI) and also from various versions of the Python Standard Library.

PyPIContents is an application that generates a Module Index from the Python Package Index (PyPI) and also from various versions of the Python Standar

Collage Labs 10 Nov 19, 2022
Python based scripts for obtaining system information from Linux.

sysinfo Python based scripts for obtaining system information from Linux. Python2 and Python3 compatible Output in JSON format Simple scripts and exte

Petr Vavrin 70 Dec 20, 2022
Um Script De Mensagem anonimas Para linux e Termux Feito em python

Um Script De Mensagem anonimas Para linux e Termux Feito em python feito em um celular

null 6 Sep 9, 2021
Hashcrack - A non-object oriented open source, Software for Windows/Linux made in Python 3

Multi Force This project is a non-object oriented open source, Software for Wind

Radiationbolt 3 Jan 2, 2023
A simple and easy to use Python's PIP configuration manager, similar to the Arch Linux's Java manager.

PIPCONF - The PIP configuration manager If you need to manage multiple configurations containing indexes and trusted hosts for PIP, this project was m

João Paulo Carvalho 11 Nov 30, 2022
Python 3 script for installing kali tools on your linux machine

Python 3 script for installing kali tools on your linux machine

gh0st 2 Apr 20, 2022
A Linux webcam plugin for BGMv2 as used in our demos.

The goal of this repository is to supplement the main Real-Time High Resolution Background Matting repo with a working demo of a videoconferencing plu

Andrey Ryabtsev 144 Dec 27, 2022
HPomb Is Socail Engineering Tool , Used For Bombing , Spoofing and Anonymity Available For Linux And Android(Termux)

HPomb v2020.02 Coming Soon Created By Secanonm HPomb Is Socail Engineering Tool , Used For Bombing , Spoofing and Anonymity Available For Linux And An

Secanonm 10 Jul 25, 2022
Tool to generate wrappers for Linux libraries allowing for dlopen()ing them without writing any boilerplate

Dynload wrapper This program will generate a wrapper to make it easy to dlopen() shared objects on Linux without writing a ton of boilerplate code. Th

Hein-Pieter van Braam 25 Oct 24, 2022
Hook and simulate global keyboard events on Windows and Linux.

keyboard Take full control of your keyboard with this small Python library. Hook global events, register hotkeys, simulate key presses and much more.

BoppreH 3.2k Jan 1, 2023
The earliest beta version of pytgcalls on Linux x86_64 and ARM64! Use in production at your own risk!

Public beta test. Use in production at your own risk! tgcalls - a python binding for tgcalls (c++ lib by Telegram); pytgcalls - library connecting pyt

Il'ya 21 Jan 13, 2022
pspsps(1) is a compyuter software to call an online catgirl to the Linux terminyal.

pspsps(1): call a catgirl from the Internyet to the Linux terminyal show processes: ps show catgirls: pspsps —@[email protected] pspsps(1) is a compyute

Melissa Boiko 32 Dec 19, 2022
GNU/Linux'u yeni kurulumu bitirmiş olarak açtığınızda sizi karşılayacak bir uygulama.

Hoş Geldiniz GNU/Linux'u yeni kurulumu bitirmiş olarak açtığınızda sizi karşılayacak bir uygulama.

Alperen İsa 96 Oct 30, 2022
Runs macOS on linux with qemu.

mac-on-linux-with-qemu Runs macOS on linux with qemu. Pre-requisites qemu-system-x86_64 dmg2img pulseaudio python[click] Usage After cloning the repos

Arindam Das 177 Dec 26, 2022