Python

Как сделать скриншот с помощью скрипта Python в Linux

Я хочу сделать снимок экрана с помощью скрипта python и сохранить его. Меня интересует только решение для Linux, и я должен поддерживать любую среду на основе любой системы.

 

Ответ 1

Это работает без использования scrot или ImageMagick.

import gtk.gdk

 

w = gtk.gdk.get_default_root_window()

sz = w.get_size()

print "Размер окнаs %d на %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.png."

else:

    print "Не удалось получить скриншот."

 

Ответ 2

Все варианты, сгруппированные в одном классе. Вывод изображения через библиотеку 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 __name__ == '__main__':

    s = screengrab()

    screen = s.screen()

    screen.show()

 

Ответ 3

Для полноты: библиотека Xlib, однако при захвате всего экрана она несколько медленная:

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

Можно попробовать добавить некоторые типы в файлы-узкие места в PyXlib, а затем скомпилировать их с помощью Cython. Это может немного увеличить скорость.

Можно написать ядро функции на C, а затем использовать ее в python из ctypes, вот что можно сделать вместе:

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

}

И затем 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 __name__ == '__main__':

  im = grab_screen(0,0,1440,900)

  im.show()

 

Ответ 4

Кроссплатформенное решение с использованием wxPython:

import wx

wx.App()  # Необходимо создать экземпляр приложения, прежде чем что-либо делать

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)

 

Схожие статьи

Выход из цикла в С и Python: как правильно останавливать
Python

Выход из цикла в С и Python: как правильно останавливать

Оптимизация Python: простые способы ускорить и очистить код
Python

Оптимизация Python: простые способы ускорить и очистить код

Инструкция для новичков в Python: как открыть файл в Питоне?
Python

Инструкция для новичков в Python: как открыть файл в Питоне?

5 лучших языков программирования для детей
Python

5 лучших языков программирования для детей