Take a screenshot via a Python script on Linux

I want to take a screenshot via a python script and unobtrusively save it.

I'm only interested in the Linux solution, and should support any X based environment.


Asked by: Vivian213 | Posted: 05-10-2021






Answer 1

This works without having to use scrot or ImageMagick.

import gtk.gdk

w = gtk.gdk.get_default_root_window()
sz = w.get_size()
print "The size of the window is %d x %d" % sz
pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
if (pb != None):
    pb.save("screenshot.png","png")
    print "Screenshot saved to screenshot.png."
else:
    print "Unable to get the screenshot."

Borrowed from http://ubuntuforums.org/showpost.php?p=2681009&postcount=5

Answered by: Roland733 | Posted: 06-11-2021



Answer 2

Just for completeness: Xlib - But it's somewhat slow when capturing the whole screen:

from Xlib import display, X
import Image #PIL

W,H = 200,200
dsp = display.Display()
try:
    root = dsp.screen().root
    raw = root.get_image(0, 0, W,H, X.ZPixmap, 0xffffffff)
    image = Image.fromstring("RGB", (W, H), raw.data, "raw", "BGRX")
    image.show()
finally:
    dsp.close()

One could try to trow some types in the bottleneck-files in PyXlib, and then compile it using Cython. That could increase the speed a bit.


Edit: We can write the core of the function in C, and then use it in python from ctypes, here is something I hacked together:

#include <stdio.h>
#include <X11/X.h>
#include <X11/Xlib.h>
//Compile hint: gcc -shared -O3 -lX11 -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c

void getScreen(const int, const int, const int, const int, unsigned char *);
void getScreen(const int xx,const int yy,const int W, const int H, /*out*/ unsigned char * data) 
{
   Display *display = XOpenDisplay(NULL);
   Window root = DefaultRootWindow(display);

   XImage *image = XGetImage(display,root, xx,yy, W,H, AllPlanes, ZPixmap);

   unsigned long red_mask   = image->red_mask;
   unsigned long green_mask = image->green_mask;
   unsigned long blue_mask  = image->blue_mask;
   int x, y;
   int ii = 0;
   for (y = 0; y < H; y++) {
       for (x = 0; x < W; x++) {
         unsigned long pixel = XGetPixel(image,x,y);
         unsigned char blue  = (pixel & blue_mask);
         unsigned char green = (pixel & green_mask) >> 8;
         unsigned char red   = (pixel & red_mask) >> 16;

         data[ii + 2] = blue;
         data[ii + 1] = green;
         data[ii + 0] = red;
         ii += 3;
      }
   }
   XDestroyImage(image);
   XDestroyWindow(display, root);
   XCloseDisplay(display);
}

And then the python-file:

import ctypes
import os
from PIL import Image

LibName = 'prtscn.so'
AbsLibPath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + LibName
grab = ctypes.CDLL(AbsLibPath)

def grab_screen(x1,y1,x2,y2):
    w, h = x2-x1, y2-y1
    size = w * h
    objlength = size * 3

    grab.getScreen.argtypes = []
    result = (ctypes.c_ubyte*objlength)()

    grab.getScreen(x1,y1, w, h, result)
    return Image.frombuffer('RGB', (w, h), result, 'raw', 'RGB', 0, 1)
    
if __name__ == '__main__':
  im = grab_screen(0,0,1440,900)
  im.show()

Answered by: John859 | Posted: 06-11-2021



Answer 3

Compile all answers in one class. Outputs PIL image.

#!/usr/bin/env python
# encoding: utf-8
"""
screengrab.py

Created by Alex Snet on 2011-10-10.
Copyright (c) 2011 CodeTeam. All rights reserved.
"""

import sys
import os

import Image


class screengrab:
    def __init__(self):
        try:
            import gtk
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByGtk

        try:
            import PyQt4
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByQt

        try:
            import wx
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByWx

        try:
            import ImageGrab
        except ImportError:
            pass
        else:
            self.screen = self.getScreenByPIL


    def getScreenByGtk(self):
        import gtk.gdk      
        w = gtk.gdk.get_default_root_window()
        sz = w.get_size()
        pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
        pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
        if pb is None:
            return False
        else:
            width,height = pb.get_width(),pb.get_height()
            return Image.fromstring("RGB",(width,height),pb.get_pixels() )

    def getScreenByQt(self):
        from PyQt4.QtGui import QPixmap, QApplication
        from PyQt4.Qt import QBuffer, QIODevice
        import StringIO
        app = QApplication(sys.argv)
        buffer = QBuffer()
        buffer.open(QIODevice.ReadWrite)
        QPixmap.grabWindow(QApplication.desktop().winId()).save(buffer, 'png')
        strio = StringIO.StringIO()
        strio.write(buffer.data())
        buffer.close()
        del app
        strio.seek(0)
        return Image.open(strio)

    def getScreenByPIL(self):
        import ImageGrab
        img = ImageGrab.grab()
        return img

    def getScreenByWx(self):
        import wx
        wx.App()  # Need to create an App instance before doing anything
        screen = wx.ScreenDC()
        size = screen.GetSize()
        bmp = wx.EmptyBitmap(size[0], size[1])
        mem = wx.MemoryDC(bmp)
        mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
        del mem  # Release bitmap
        #bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)
        myWxImage = wx.ImageFromBitmap( myBitmap )
        PilImage = Image.new( 'RGB', (myWxImage.GetWidth(), myWxImage.GetHeight()) )
        PilImage.fromstring( myWxImage.GetData() )
        return PilImage

if __name__ == '__main__':
    s = screengrab()
    screen = s.screen()
    screen.show()

Answered by: Lyndon749 | Posted: 06-11-2021



Answer 4

This one works on X11, and perhaps on Windows too (someone, please check). Needs PyQt4:

import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')

Answered by: Anna675 | Posted: 06-11-2021



Answer 5

I have a wrapper project (pyscreenshot) for scrot, imagemagick, pyqt, wx and pygtk. If you have one of them, you can use it. All solutions are included from this discussion.

Install:

easy_install pyscreenshot

Example:

import pyscreenshot as ImageGrab

# fullscreen
im=ImageGrab.grab()
im.show()

# part of the screen
im=ImageGrab.grab(bbox=(10,10,500,500))
im.show()

# to file
ImageGrab.grab_to_file('im.png')

Answered by: Emma856 | Posted: 06-11-2021



Answer 6

Cross platform solution using wxPython:

import wx
wx.App()  # Need to create an App instance before doing anything
screen = wx.ScreenDC()
size = screen.GetSize()
bmp = wx.EmptyBitmap(size[0], size[1])
mem = wx.MemoryDC(bmp)
mem.Blit(0, 0, size[0], size[1], screen, 0, 0)
del mem  # Release bitmap
bmp.SaveFile('screenshot.png', wx.BITMAP_TYPE_PNG)

Answered by: Wilson867 | Posted: 06-11-2021



Answer 7

import ImageGrab
img = ImageGrab.grab()
img.save('test.jpg','JPEG')

this requires Python Imaging Library

Answered by: David281 | Posted: 06-11-2021



Answer 8

You can use this

import os
os.system("import -window root screen_shot.png")

Answered by: Aston540 | Posted: 06-11-2021



Answer 9

I couldn't take screenshot in Linux with pyscreenshot or scrot because output of pyscreenshot was just a black screen png image file.

but thank god there was another very easy way for taking screenshot in Linux without installing anything. just put below code in your directory and run with python demo.py

import os
os.system("gnome-screenshot --file=this_directory.png")

also there is many available options for gnome-screenshot --help

Application Options:
  -c, --clipboard                Send the grab directly to the clipboard
  -w, --window                   Grab a window instead of the entire screen
  -a, --area                     Grab an area of the screen instead of the entire screen
  -b, --include-border           Include the window border with the screenshot
  -B, --remove-border            Remove the window border from the screenshot
  -p, --include-pointer          Include the pointer with the screenshot
  -d, --delay=seconds            Take screenshot after specified delay [in seconds]
  -e, --border-effect=effect     Effect to add to the border (shadow, border, vintage or none)
  -i, --interactive              Interactively set options
  -f, --file=filename            Save screenshot directly to this file
  --version                      Print version information and exit
  --display=DISPLAY              X display to use

Answered by: Ted684 | Posted: 06-11-2021



Answer 10

bit late but nevermind easy one is

import autopy
import time
time.sleep(2)
b = autopy.bitmap.capture_screen()
b.save("C:/Users/mak/Desktop/m.png")

Answered by: Aston976 | Posted: 06-11-2021



Answer 11

There is a python package for this Autopy

The bitmap module can to screen grabbing (bitmap.capture_screen) It is multiplateform (Windows, Linux, Osx).

Answered by: Kellan719 | Posted: 06-11-2021



Answer 12

for ubuntu this work for me, you can take a screenshot of select window with this:

import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')

from gi.repository import Gdk
from gi.repository import GdkPixbuf
import numpy as np
from Xlib.display import Display

#define the window name
window_name = 'Spotify'

#define xid of your select 'window'
def locate_window(stack,window):
    disp = Display()
    NET_WM_NAME = disp.intern_atom('_NET_WM_NAME')
    WM_NAME = disp.intern_atom('WM_NAME') 
    name= []
    for i, w in enumerate(stack):
        win_id =w.get_xid()
        window_obj = disp.create_resource_object('window', win_id)
        for atom in (NET_WM_NAME, WM_NAME):
            window_name=window_obj.get_full_property(atom, 0)
            name.append(window_name.value)
    for l in range(len(stack)):
        if(name[2*l]==window):
            return stack[l]

window = Gdk.get_default_root_window()
screen = window.get_screen()
stack = screen.get_window_stack()
myselectwindow = locate_window(stack,window_name)
img_pixbuf = Gdk.pixbuf_get_from_window(myselectwindow,*myselectwindow.get_geometry()) 

to transform pixbuf into array

def pixbuf_to_array(p):
    w,h,c,r=(p.get_width(), p.get_height(), p.get_n_channels(), p.get_rowstride())
    assert p.get_colorspace() == GdkPixbuf.Colorspace.RGB
    assert p.get_bits_per_sample() == 8
    if  p.get_has_alpha():
        assert c == 4
    else:
        assert c == 3
    assert r >= w * c
    a=np.frombuffer(p.get_pixels(),dtype=np.uint8)
    if a.shape[0] == w*c*h:
        return a.reshape( (h, w, c) )
    else:
        b=np.zeros((h,w*c),'uint8')
        for j in range(h):
            b[j,:]=a[r*j:r*j+w*c]
        return b.reshape( (h, w, c) )

beauty_print = pixbuf_to_array(img_pixbuf)

Answered by: Julian861 | Posted: 06-11-2021



Answer 13

From this thread:

 import os
 os.system("import -window root temp.png")

Answered by: Dainton865 | Posted: 06-11-2021



Answer 14

It's an old question. I would like to answer it using new tools.

Works with python 3 (should work with python 2, but I haven't test it) and PyQt5.

Minimal working example. Copy it to the python shell and get the result.

from PyQt5.QtWidgets import QApplication
app = QApplication([])
screen = app.primaryScreen()
screenshot = screen.grabWindow(QApplication.desktop().winId())
screenshot.save('/tmp/screenshot.png')

Answered by: First Name566 | Posted: 06-11-2021



Answer 15

Try it:

#!/usr/bin/python

import gtk.gdk
import time
import random
import socket
import fcntl
import struct
import getpass
import os
import paramiko     

while 1:
    # generate a random time between 120 and 300 sec
    random_time = random.randrange(20,25)
    # wait between 120 and 300 seconds (or between 2 and 5 minutes) 

    print "Next picture in: %.2f minutes" % (float(random_time) / 60)

    time.sleep(random_time)
    w = gtk.gdk.get_default_root_window()   
    sz = w.get_size()
    print "The size of the window is %d x %d" % sz
    pb = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,sz[0],sz[1])
    pb = pb.get_from_drawable(w,w.get_colormap(),0,0,0,0,sz[0],sz[1])
    ts = time.asctime( time.localtime(time.time()) )
    date = time.strftime("%d-%m-%Y")
    timer = time.strftime("%I:%M:%S%p")
    filename = timer
    filename += ".png"

    if (pb != None):
        username = getpass.getuser() #Get username
        newpath = r'screenshots/'+username+'/'+date #screenshot save path
        if not os.path.exists(newpath): os.makedirs(newpath)
        saveas = os.path.join(newpath,filename)
        print saveas
        pb.save(saveas,"png")
    else:
        print "Unable to get the screenshot."

Answered by: Paul850 | Posted: 06-11-2021



Similar questions

python - Screenshot script can't save the .png image with the actual date

I'm writing a python script to screenshot every 30 seconds and save the output image with the actual date. The problem is that the script is saving each image with each letter of the time.ctime() output (Tue Jan 3 01:30:53 2017): T.png u.png e.png ... How can i save each image output with the actual complete date ? import pyscreenshot as Ima...


macos - Take screenshot in Python on Mac OS X

ImageGrab from PIL would have been ideal. I'm looking for similar functionality, specifically the ability to define the screenshot's bounding box. I've been looking for a library to do so on Mac OS X but haven't had any luck. I also wasn't able to find any sample code to do it (maybe pyobjc?).


python - Take a screenshot of an iFrame using pyside

I have an issue taking screenshots of a Google-translated page. The below script is working fine (takes a screenshot) without Google translate: class Render(QWebPage): def __init__(self, url): self.web_page = QWebPage() self.finished = False s = self.web_page.settings() s.setAttribute(QWebSettings.JavascriptCanOpenWindows, False) s.setAttribute(QWebSetti...


python - Pygame movie screenshot

I am trying to take a screenshot of every frame of a movie for other processing. However, when I run this, all I get is newlines printed out. After I kill the program in any way, I get a Segmentation fault (core dumped) Why is the segmentation fault happening? My code or pygame or somthing else? Why do I not get some text out of the program? Using Python 2.7, Ubuntu import sys import...


python - How to blit a PyQt screenshot to PyGame Window

I have a program that is supposed to take screenshots... #imports pyqt from PyQt4.QtGui import QPixmap, QApplication #declares variables date = datetime.datetime.now() counter = 0 #sets directory to be used to save screenshots directorydate = str(date.year) + str(date.month) + str(date.day) + str(date.hour) +str(date.minute) + str(date.second) directory = os.path.abspath('Photos%s' % directorydate) #some...


python - Take a screenshot of an html file with vba

I'm working on a set of html files (saved on a local drive from the web with some python code) and I'm looking up keywords in these files. They are several pages long however and I'm struggling to find a way to automate the following sequence with vba : Open file > look up keyword1 > take a screenshot centered on keyword1 with x width and y height > Save under best format (jpeg?) on local drive > go to the next keyword > g...


python - Pyqt take screenshot of certain screen area

I have this app written in pyqt. You can view the source at http://www.pasteall.org/62739/python It takes screen shots of the desktop. what I want to know is how to make it also take a screen shot of a certain area on the screen like window's snipping tool can do (


Python open html file, take screenshot, crop and save as image

I am using the Bokeh package to generate maps to show the results of a simulation. The output is individual maps in html format with interactivity. The interactivity is needed for individual maps. See this link for an example: http://docs.bokeh.org/en/0.10.0/docs/gallery/texas.html The simulation can au...


python - Taking fast screenshot Winapi and Opencv

I need to take very fast screenshots of a game for an OpenCV project I am working on. I can use PIL easily for example: def take_screenshot1(hwnd): rect = win32gui.GetWindowRect(hwnd) img = ImageGrab.grab(bbox=rect) img_np = np.array(img) return cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR) But it takes on average of 0.05 seconds which isn't fast enough for real time capture....


python - Black screenshot using Pyglet

I've been trying to grab a screenshot of a window I created using the Pyglet module of Python. I used this line of code to grab the screenshot: pyglet.image.get_buffer_manager().get_color_buffer().save('screenshot1.png') Though there is no error occurring when I'm running the program and the screenshot file is created, the file is just black. Here is the complete code: impo...


python - Screenshot script can't save the .png image with the actual date

I'm writing a python script to screenshot every 30 seconds and save the output image with the actual date. The problem is that the script is saving each image with each letter of the time.ctime() output (Tue Jan 3 01:30:53 2017): T.png u.png e.png ... How can i save each image output with the actual complete date ? import pyscreenshot as Ima...


jquery - Using PiL to take a screenshot of HTML/CSS

I want to enable a user on a website to upload an image, and write some text over it. Also, they should be able to crop/scale/move the image and text. For that stuff, I can do it in jQuery. After they've made the image the way they want it, is there a way i can take a screenshot of that image (using PiL) and save it on the server? What is the best/proper way to do this?


screenshot - How to kill headless X server started via Python?

I want to get screenshots of a webpage in Python. For this I am using http://github.com/AdamN/python-webkit2png/ . newArgs = ["xvfb-run", "--server-args=-screen 0, 640x480x24", sys.argv[0]] for i in range(1, len(sys.argv)): if sys.argv[i] not in ["-x", "--xvfb"]: newArgs.append(sys.argv[i]) log...


python - Is there a way to prevent detection by the website when a screenshot is taken using a Mac Os X Safari browser?

There is a thread discussing Darwin notifications being sent after a screenshot is taken. Does this apply to websites viewed via Safari? Do the same restrictions apply to PC sytems? Would taking the picture via a Python script in Linux or running Safari in a VM circumvent detection?


Python on windows, shutting down and taking a screenshot

I have the following two quesions: 1 I want to be able to shutdown windows xp from python code. I am able to do that by running the following code in the python console: import os os.system("shutdown -s -f") But, if i put the same code in a .py file and try to execute it,it does not work. I get the help prompt for the shutdown command.Any way to fix this ? 2 Is there any w...


Fastest way to take a screenshot with python on windows

What's the fastest way to take a screenshot on windows? PIL.ImageGrab is rather slow.. it takes between 4-5 seconds to take 30 screenshots of the same small window. Taking screenshots of the whole desktop is even slower.


php - Convert URL to screenshot (script)

There is the URL of page on the Internet. I need to get a screenshot of this page (no matter in which browser). I need a script (PHP, Python (even Django framework)) that receives the URL (string) and output screenshot-file at the exit (file gif, png, jpg). UPD: I need dynamically create a page where opposite to URL will be placed screenshot of the page with the same URL.


screenshot - Selecting area of the screen with Python

I'm developing a screen shot utility in Python. At the moment it is specifically for Linux. So far I have the ability to take a screen shot of the full desktop, and have it upload to Imgur, then copy the link to clipboard. Now I want to expand into functions such as screen shots of the active window, or of a specific selection. If anyone could help, I'd love to know what kind of module would work best for this, and how to ...


macos - Take screenshot in Python on Mac OS X

ImageGrab from PIL would have been ideal. I'm looking for similar functionality, specifically the ability to define the screenshot's bounding box. I've been looking for a library to do so on Mac OS X but haven't had any luck. I also wasn't able to find any sample code to do it (maybe pyobjc?).


image - Python windows 7 screenshot without PIL

I want to take a screenshot using python. I have tried using PIL, but since I am using 64bit windows and python PIL does not work (I could only find 32bit PIL versions). I am using python 2.7.1 by the way. I want to take a screenshot, it doesn't really matter how, as long as it can take more than 1 per second in speed. Preferably it should also be able to crop the area it takes a screenshot of, but that's n...


Taking screenshot from a python script by selecting the area

I saw that post (that is really helpful : Take a screenshot via a python script. [Linux]) about taking a screenshot from python. It works well but I'd like to have the same behavior as gnome-screenshot : having the possibility to choose between : Capturing the whole desktop Capturing an active window






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top