Я хочу сделать снимок экрана с помощью скрипта python и ненавязчиво его сохранить.
Меня интересует только решение Linux, и я должен поддерживать любую среду на основе X.
python
linux
screenshot
скайроник
источник
источник
Ответы:
Это работает без использования scrot или 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."
Заимствовано с http://ubuntuforums.org/showpost.php?p=2681009&postcount=5
источник
Соберите все ответы в одном классе. Выводит изображение 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()
источник
getScreenByWx
метод не работаетwx._core.PyNoAppError: The wx.App object must be created first!
. Как ни странно, код работает нормально, если вы вводите его построчно в оболочке python, но в сценарии он не работает.getScreenByWx
вам следует: а) заменитьmyBitmap
наbmp
и б) сохранитьwx.App()
в переменную. ВgetScreenByGtk
заменить(pb != None)
наpb is None
. И не используйте Qt, поэтому - вы не можете создать два разаQApplication
- ваше приложение выйдет из строя при попытке создать его второй раз.Для полноты: Xlib - Но при захвате всего экрана он несколько медленный:
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()
Можно попробовать добавить некоторые типы в файлы-узкие места в 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()
источник
#include <X11/Xutil.h>
вместо#include <X11/Xlib.h>
. Кроме того, для компиляции, я должен был двигаться-lX11
до конца , как это:gcc -shared -O3 -Wall -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c -lX11
.Этот работает на X11 и, возможно, на Windows тоже (кто-нибудь, пожалуйста, проверьте). Требуется PyQt4 :
import sys from PyQt4.QtGui import QPixmap, QApplication app = QApplication(sys.argv) QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')
источник
У меня есть проект-оболочка ( снимок экрана ) для scrot, imagemagick, pyqt, wx и pygtk. Если у вас есть один из них, вы можете его использовать. Все решения включены в это обсуждение.
Установить:
Пример:
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')
источник
pyscreenshot.tempexport.RunProgError: No protocol specified giblib error: Can't open X display. It *is* running, yeah?" timeout_happened=False>
Кросс-платформенное решение с использованием 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)
источник
import ImageGrab img = ImageGrab.grab() img.save('test.jpg','JPEG')
для этого требуется библиотека изображений Python
источник
Вы можете использовать это
import os os.system("import -window root screen_shot.png")
источник
немного поздно, но неважно, легкий
import autopy import time time.sleep(2) b = autopy.bitmap.capture_screen() b.save("C:/Users/mak/Desktop/m.png")
источник
Я не мог сделать снимок экрана в Linux с помощью pyscreenshot или scrot, потому что вывод
pyscreenshot
был просто файлом изображения png с черным экраном.но, слава богу, был еще один очень простой способ сделать снимок экрана в Linux, ничего не устанавливая. просто поместите код ниже в свой каталог и запустите с
python demo.py
import os os.system("gnome-screenshot --file=this_directory.png")
также есть много доступных вариантов для
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
источник
Для этого Autopy есть пакет python
Модуль растрового изображения может захватывать экран (bitmap.capture_screen). Он многоплатформенный (Windows, Linux, Osx).
источник
Из этой темы :
import os os.system("import -window root temp.png")
источник
для ubuntu это работает для меня, вы можете сделать снимок экрана окна выбора следующим образом:
import gi gi.require_version('Gtk', '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())
преобразовать pixbuf в массив
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)
источник
Это старый вопрос. Я хотел бы ответить на него новыми инструментами.
Работает с python 3 (должен работать с python 2, но я его не тестировал) и PyQt5.
Минимальный рабочий пример. Скопируйте его в оболочку python и получите результат.
from PyQt5.QtWidgets import QApplication app = QApplication([]) screen = app.primaryScreen() screenshot = screen.grabWindow(QApplication.desktop().winId()) screenshot.save('/tmp/screenshot.png')
источник
Попытайся:
#!/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."
источник
while
цикл, который никогда не завершается (и использует1
вместоTrue
),if (pb != None):
вместо простоif pb:
имеет бессмысленные необработанные строки.