Tôi muốn chụp ảnh màn hình thông qua tập lệnh python và lưu nó một cách kín đáo.
Tôi chỉ quan tâm đến giải pháp Linux và sẽ hỗ trợ bất kỳ môi trường dựa trên X.
Tôi muốn chụp ảnh màn hình thông qua tập lệnh python và lưu nó một cách kín đáo.
Tôi chỉ quan tâm đến giải pháp Linux và sẽ hỗ trợ bất kỳ môi trường dựa trên X.
Câu trả lời:
Điều này hoạt động mà không cần phải sử dụng scrot hoặc 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."
Mượn từ http://ubuntuforums.org/showpost.php?p=2681009&postcount=5
Biên dịch tất cả các câu trả lời trong một lớp. Xuất hình ảnh 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
phương pháp này không thành công với wx._core.PyNoAppError: The wx.App object must be created first!
. Thật thú vị, mã hoạt động tốt nếu bạn nhập từng dòng một trong trình bao python nhưng trong một tập lệnh, nó không thành công.
getScreenByWx
Bạn nên a) thay thế myBitmap
bằng bmp
và b) lưu wx.App()
vào một biến. Thay getScreenByGtk
thế (pb != None)
thành pb is None
. Và đừng sử dụng Qt vì vậy - bạn không thể tạo hai lần QApplication
- ứng dụng của bạn sẽ gặp sự cố khi cố tạo lần thứ hai.
Chỉ để hoàn thiện: Xlib - Nhưng hơi chậm khi chụp toàn màn hình:
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()
Người ta có thể cố gắng loại bỏ một số loại trong các tệp nút cổ chai trong PyXlib, và sau đó biên dịch nó bằng Cython. Điều đó có thể tăng tốc độ một chút.
Chỉnh sửa: Chúng ta có thể viết cốt lõi của hàm trong C, sau đó sử dụng nó trong python từ ctypes, đây là thứ mà tôi đã hack cùng nhau:
#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);
}
Và sau đó là tệp 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>
thay thế #include <X11/Xlib.h>
. Còn cho biên soạn, tôi đã phải di chuyển -lX11
đến cuối như thế này: gcc -shared -O3 -Wall -fPIC -Wl,-soname,prtscn -o prtscn.so prtscn.c -lX11
.
Cái này hoạt động trên X11 và có lẽ cũng trên Windows (ai đó, vui lòng kiểm tra). Cần PyQt4 :
import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('test.png', 'png')
Tôi có một dự án trình bao bọc ( pyscreenshot ) cho scrot, imagemagick, pyqt, wx và pygtk. Nếu bạn có một trong số chúng, bạn có thể sử dụng nó. Tất cả các giải pháp được bao gồm từ cuộc thảo luận này.
Tải về:
easy_install pyscreenshot
Thí dụ:
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>
Giải pháp đa nền tảng sử dụng 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')
điều này yêu cầu Thư viện hình ảnh Python
Bạn có thể sử dụng cái này
import os
os.system("import -window root screen_shot.png")
Tôi không thể chụp ảnh màn hình trong Linux bằng pyscreenshot hoặc scrot vì đầu ra của pyscreenshot
chỉ là một tệp hình ảnh png màn hình đen.
nhưng cảm ơn chúa, có một cách khác rất dễ dàng để chụp ảnh màn hình trong Linux mà không cần cài đặt bất kỳ thứ gì. chỉ cần đặt mã bên dưới vào thư mục của bạn và chạy vớipython demo.py
import os
os.system("gnome-screenshot --file=this_directory.png")
cũng có nhiều tùy chọn có sẵn cho 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
Từ chủ đề này :
import os
os.system("import -window root temp.png")
đối với ubuntu, công việc này đối với tôi, bạn có thể chụp ảnh màn hình của cửa sổ chọn với cái này:
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())
chuyển pixbuf thành mảng
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)
Đó là một câu hỏi cũ. Tôi muốn trả lời nó bằng cách sử dụng các công cụ mới.
Hoạt động với python 3 (nên hoạt động với python 2, nhưng tôi chưa thử nghiệm nó) và PyQt5.
Ví dụ làm việc tối thiểu. Sao chép nó vào trình bao python và nhận kết quả.
from PyQt5.QtWidgets import QApplication
app = QApplication([])
screen = app.primaryScreen()
screenshot = screen.grabWindow(QApplication.desktop().winId())
screenshot.save('/tmp/screenshot.png')
Thử nó:
#!/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
vòng lặp không bao giờ thoát (và sử dụng 1
thay vì True
), if (pb != None):
thay vì chỉ if pb:
, có một số chuỗi thô vô nghĩa.