Python:获取和保存屏幕截图的最快方法

时间:2017-02-01 10:33:03

标签: python gtk python-imaging-library ctypes pygtk

我一直在努力想出一个允许我每秒多次截取桌面截图的脚本。我使用的是Win10。

PIL:

from PIL import ImageGrab
import time

while True:
    im = ImageGrab.grab()
    fname = "dropfolder/%s.png" %int(time.time())
    im.save(fname,'PNG') 

每张图片的结果为1.01秒。

PyScreeze(https://github.com/asweigart/pyscreeze):

import pyscreeze
import time

while True:
    fname = "dropfolder/%s.png" %int(time.time())
    x = pyscreeze.screenshot(fname)

每张图片的结果为1.00秒。

的Win32:

import win32gui
import win32ui 
import win32con
import time

w=1920 #res
h=1080 #res

while True:
    wDC = win32gui.GetWindowDC(0)
    dcObj=win32ui.CreateDCFromHandle(wDC)
    cDC=dcObj.CreateCompatibleDC()
    dataBitMap = win32ui.CreateBitmap()
    dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
    cDC.SelectObject(dataBitMap)
    cDC.BitBlt((0,0),(w, h) , dcObj, (0,0), win32con.SRCCOPY)
    fname = "dropfolder/%s.png" %int(time.time())
    dataBitMap.SaveBitmapFile(cDC, fname)
    dcObj.DeleteDC()
    cDC.DeleteDC()
    win32gui.ReleaseDC(0, wDC)
    win32gui.DeleteObject(dataBitMap.GetHandle())

每张图片的结果为1.01秒。

然后我偶然发现线程(Fastest way to take a screenshot with python on windows),建议gtk会产生惊人的结果。

但是使用gtk:

import gtk
import time

img_width = gtk.gdk.screen_width()
img_height = gtk.gdk.screen_height()

while True:
    screengrab = gtk.gdk.Pixbuf(
        gtk.gdk.COLORSPACE_RGB,
        False,
        8,
        img_width,
        img_height
    )

    fname = "dropfolder/%s.png" %int(time.time())
    screengrab.get_from_drawable(
        gtk.gdk.get_default_root_window(),
        gtk.gdk.colormap_get_system(),
        0, 0, 0, 0,
        img_width,
        img_height
        ).save(fname, 'png')

每张图片的结果为2.34秒。

在我看来,我做错了什么,因为人们用gtk获得了很好的结果。

有关如何加快流程的建议吗?

谢谢!

2 个答案:

答案 0 :(得分:2)

您的第一个解决方案应该是每秒为您提供多张图片。但问题是你将覆盖在同一秒内发生的任何图片,即它们都将具有相同的文件名。要解决此问题,您可以创建包含10秒的文件名,如下所示:

from PIL import ImageGrab
from datetime import datetime

while True:
    im = ImageGrab.grab()
    dt = datetime.now()
    fname = "pic_{}.{}.png".format(dt.strftime("%H%M_%S"), dt.microsecond // 100000)
    im.save(fname, 'png') 

在我的机器上,这给出了以下输出:

pic_1143_24.5.png
pic_1143_24.9.png
pic_1143_25.3.png
pic_1143_25.7.png
pic_1143_26.0.png
pic_1143_26.4.png
pic_1143_26.8.png
pic_1143_27.2.png

答案 1 :(得分:1)

def d3dgrab(rect=(0, 0, 0, 0), spath=r".\\pictures\\cache\\", sname="", title=""):
    """ take a screenshot by rect. """

    sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
    while os.path.isfile("%s%s" % (spath, sname)):
        sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])

    xlen = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
    ylen = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)

    assert 0 <= rect[0] <= xlen and 0 <= rect[2] <= xlen, ValueError("Illegal value of X coordination in rect: %s" % rect)
    assert 0 <= rect[1] <= ylen and 0 <= rect[3] <= ylen, ValueError("Illegal value of Y coordinatoin in rect: %s" % rect)

    if title:
        hdl = win32gui.FindWindow(None, title)
        if hdl != win32gui.GetForegroundWindow():
            win32gui.SetForegroundWindow(hdl)
        rect = win32gui.GetWindowRect(hdl)
    elif not sum(rect):
        rect = (0, 0, xlen, ylen)

    d = d3dshot.create(capture_output="numpy")
    return d.screenshot_to_disk(directory=spath, file_name=sname, region=rect)

我认为这会有所帮助

sname = sname if sname else time.strftime("%Y%m%d%H%M%S000.jpg", time.localtime())
while os.path.isfile("%s%s" % (spath, sname)):
    sname = "%s%03d%s" % (sname[:-7], int(sname[-7:-4]) + 1, sname[-4:])

这是获取我发现的屏幕截图的最快方法。