Take a screenshot via a Python script on Linux

PythonLinuxScreenshot

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

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

Solution 2 - Python

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()

Solution 3 - Python

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()

Solution 4 - Python

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')

Solution 5 - Python

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')

Solution 6 - Python

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)

Solution 7 - Python

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

this requires Python Imaging Library

Solution 8 - Python

You can use this

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

Solution 9 - Python

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

Solution 10 - Python

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")

Solution 11 - Python

There is a python package for this Autopy

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

Solution 12 - Python

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)

Solution 13 - Python

From this thread:

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

Solution 14 - Python

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')

Solution 15 - Python

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."

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionskyronicView Question on Stackoverflow
Solution 1 - PythonRustyView Answer on Stackoverflow
Solution 2 - PythonJHoltaView Answer on Stackoverflow
Solution 3 - PythonAlex RaederView Answer on Stackoverflow
Solution 4 - PythonJulianoView Answer on Stackoverflow
Solution 5 - PythonpontyView Answer on Stackoverflow
Solution 6 - PythonSnowballView Answer on Stackoverflow
Solution 7 - PythonSlava VView Answer on Stackoverflow
Solution 8 - PythonJack SparrowView Answer on Stackoverflow
Solution 9 - PythoncyeraView Answer on Stackoverflow
Solution 10 - PythonpkmView Answer on Stackoverflow
Solution 11 - PythonouilleView Answer on Stackoverflow
Solution 12 - PythonMatheus K.View Answer on Stackoverflow
Solution 13 - PythonanderstoodView Answer on Stackoverflow
Solution 14 - PythonrominfView Answer on Stackoverflow
Solution 15 - PythonAnandView Answer on Stackoverflow