Take a screenshot via a Python script on Linux Take a screenshot via a Python script on Linux python python

Take a screenshot via a Python script on Linux


This works without having to use scrot or ImageMagick.

import gtk.gdkw = gtk.gdk.get_default_root_window()sz = w.get_size()print "The size of the window is %d x %d" % szpb = 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


Compile all answers in one class.Outputs PIL image.

#!/usr/bin/env python# encoding: utf-8"""screengrab.pyCreated by Alex Snet on 2011-10-10.Copyright (c) 2011 CodeTeam. All rights reserved."""import sysimport osimport Imageclass 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 PilImageif __name__ == '__main__':    s = screengrab()    screen = s.screen()    screen.show()


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

from Xlib import display, Ximport Image #PILW,H = 200,200dsp = 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.cvoid 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 ctypesimport osfrom PIL import ImageLibName = 'prtscn.so'AbsLibPath = os.path.dirname(os.path.abspath(__file__)) + os.path.sep + LibNamegrab = 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()