web-dev-qa-db-fra.com

Prenez une capture d'écran via un script python. [Linux]

Je veux prendre une capture d'écran via un script Python et l'enregistrer discrètement.

Je ne m'intéresse qu'à la solution Linux et je devrais prendre en charge tout environnement basé sur X.

75
skyronic

Cela fonctionne sans avoir à utiliser scrot ou 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."

Emprunté à http://ubuntuforums.org/showpost.php?p=2681009&postcount=5

64
Rusty

Compilez toutes les réponses dans une classe . Affiche l’image PIL.

#!/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 __== '__main__':
    s = screengrab()
    screen = s.screen()
    screen.show()
45
Alex Snet

Juste pour être complet: Xlib - Mais c'est un peu lent pour capturer tout l'écran:

from Xlib import display, X
import Image #PIL

W,H = 200,200
dsp = display.Display()
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()

On pourrait essayer de jeter quelques types dans les fichiers goulot d’étranglement dans PyXlib, puis de le compiler en utilisant Cython. Cela pourrait augmenter la vitesse un peu.


Edit: Nous pouvons écrire le noyau de la fonction en C, puis l’utiliser en python à partir de ctypes, voici quelque chose que j’ai piraté:

#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);
}

Et puis le fichier python:

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 __== '__main__':
  im = grab_screen(0,0,1440,900)
  im.show()
34
JHolta

Celui-ci fonctionne sur X11 et peut-être aussi sur Windows (quelqu'un, vérifiez s'il vous plaît). Besoins PyQt4 :

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

J'ai un projet d'emballage ( pyscreenshot ) pour scrot, imagemagick, pyqt, wx et pygtk . Si vous en avez un, vous pouvez l'utiliser . Toutes les solutions sont incluses dans cette discussion.

Installer:

easy_install pyscreenshot

Exemple:

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

Solution multiplateforme utilisant 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)
8
Snowball
import ImageGrab
img = ImageGrab.grab()
img.save('test.jpg','JPEG')

cela nécessite la bibliothèque d'imagerie Python

7
Slava V

Une brève recherche a révélé que gtkShots semble pouvoir vous aider, car il s’agit d’un programme de capture d’écran en python sous GPL.

3
Douglas Leeder

peu en retard, mais tant pis, on est

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

Il existe un package python pour cela Autopy

Le module bitmap peut effectuer une capture d'écran (bitmap.capture_screen) Il est multiplateforme (Windows, Linux, Osx).

2
ouille

Vous pouvez utiliser ceci

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

Je ne pouvais pas prendre de capture d'écran sous Linux avec pyscreenshot ou scrot car la sortie de pyscreenshot était simplement un fichier d’image png à écran noir.

mais dieu merci, il existait un autre moyen très simple de prendre une capture d’écran sous Linux sans rien installer. il suffit de mettre le code ci-dessous dans votre répertoire et de l'exécuter avec python demo.py

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

il y a aussi beaucoup d'options disponibles pour 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
1
cyera

De ce fil :

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

J'ai récemment écrit un package qui prend une capture d'écran à l'aide de la bibliothèque X11 et renvoie l'image sous forme de tableau numpy. J'ai en fait utilisé des suggestions qui sont mentionnées dans ce fil de discussion et améliorées. Un taux de trame typique de plus de 60 images par seconde pour une résolution de 1080p est possible sur une machine moderne. En fait, sur mon développement, une machine (âgée de 3 ans environ), j’ai réussi à obtenir 200 images par seconde. voici le lien vers le projet https://github.com/mherkazandjian/fastgrab

0
mher

C'est une vieille question. Je voudrais y répondre en utilisant de nouveaux outils.

Fonctionne avec Python 3 (devrait fonctionner avec Python 2, mais je ne l’ai pas testé) et PyQt5.

Exemple de travail minimal. Copiez-le dans le shell python et obtenez le résultat.

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