python - 有没有比 PIL.ImageGrab.grab() 更好的截屏方式?

标签 python windows windows-xp python-imaging-library python-2.5

我正在用 python 制作一个屏幕捕获程序。我当前的问题是 PIL.ImageGrab.grab() 给我的输出与 2 秒后的输出相同。例如,因为我想我不清楚,在下面的程序中,几乎所有图像都是相同的,具有相同的 Image.tostring() 值,即使我在 PIL.ImageGrab 期间移动了我的屏幕。抓取循环正在执行。

>>> from PIL.ImageGrab import grab
>>> l = []
>>> import time
>>> for a in l:
        l.append(grab())
        time.sleep(0.01)


    >>> for a in range(0, 30):
        l.append(grab())
        time.sleep(0.01)


>>> b = []
>>> for a in l:
        b.append(a.tostring())


>>> len(b)
30
>>> del l
>>> last = []
>>> a = 0
>>> a = -1
>>> last = ""
>>> same = -1
>>> for pic in b:
        if b == last:
            same = same + 1
        last = b


>>> same
28
>>> 

这是一个问题,因为所有图像都相同,但 1. 30 张图像中有 1 张图像不同。那将制作出质量绝对糟糕的视频。请告诉我是否有比 PIL.ImageGrab.grab() 更好的质量替代品。我需要捕获整个屏幕。谢谢!

编辑:

到目前为止,看起来最好的选择是使用 pywin32。我现在正在使用它,但速度很慢。我真的不关心兼容性,因为现在这个项目是个人的。每次我计算程序的帧率时,pywin32 都很慢,处于负数。请告诉我是否有更快的选择。谢谢!

最佳答案

PIL.ImageGrab 有很多替代品。

如果你想要跨平台,几乎每个主要的窗口库都有屏幕抓取功能。这是一个使用 PyQt4 的示例:

import sys
from PyQt4.QtGui import QPixmap, QApplication
app = QApplication(sys.argv)
QPixmap.grabWindow(QApplication.desktop().winId()).save('screenshot.jpg', 'jpg')

如果您想要与 Qt 认为的“桌面”的默认设置不同的东西,您需要深入研究 PyQt 或 Qt 文档。

缺点是这些跨平台窗口库在安装、分发甚至有时如何构建程序方面通常都非常繁重。

另一种方法是使用特定于 Windows 的代码。虽然可以通过 ctypes 直接访问 Windows API,但更简单的解决方案是 PyWin32 .

import win32gui, win32ui, win32con, win32api
hwin = win32gui.GetDesktopWindow()
width = win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN)
height = win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN)
left = win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN)
top = win32api.GetSystemMetrics(win32con.SM_YVIRTUALSCREEN)
hwindc = win32gui.GetWindowDC(hwin)
srcdc = win32ui.CreateDCFromHandle(hwindc)
memdc = srcdc.CreateCompatibleDC()
bmp = win32ui.CreateBitmap()
bmp.CreateCompatibleBitmap(srcdc, width, height)
memdc.SelectObject(bmp)
memdc.BitBlt((0, 0), (width, height), srcdc, (left, top), win32con.SRCCOPY)
bmp.SaveBitmapFile(memdc, 'screenshot.bmp')

与 Win32 一样,您必须准确指定“桌面”的含义;此版本指定当前 session 的“虚拟屏幕”,如果您在控制台本地运行,则它是所有监视器的组合,如果您通过终端服务运行,则它是远程 View 。如果您想要不同的东西,则必须阅读 MSDN 上的相关 Win32 文档。但在大多数情况下,将该文档转换为 PyWin32 是微不足道的。

(顺便说一句,即使我说“Win32”,同样适用于 Win64。)

关于python - 有没有比 PIL.ImageGrab.grab() 更好的截屏方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12590942/

相关文章:

windows - 有没有一种简单的方法可以检查系统上是否启用了 CredSSP?

c++ - 以编程方式告诉 Windows XP 待机

python - Spotfire 表格可视化换行文本,迭代多个具有相同名称的 vis,并使垂直滚动变得平滑

python - 使用 python 3.3 运行 pytest

javascript - 关闭应用程序时在 Windows Phone 8.1 中处理 toast 通知

c++ - 如何将一个数字(大于 8 个字节)从 char 数组转换为其 ASCII 表示形式?

c++ - 如何在 Windows XP 上获取连接的显示器类型?

python - 部署 Google App Engine 应用程序时出现 503 错误

Python-机器学习: Creating a training and test set from a list of arrays

c - _beginthread 和 WaitForSingleObject