Tha*_*tiK 9 python windows directx winapi python-imaging-library
目前我正在通过AutoItv3使用像素阅读器在运行直接X的程序中执行某些操作; 一个游戏.现在该程序工作正常,但作为一个练习我一直在python中重写它.现在我可以这样做:
import ImageGrab # Part of PIL
image = ImageGrab.grab() #Define an area to capture.
rgb = image.getpixel((1, 90)) #What pixel do we want?
Run Code Online (Sandbox Code Playgroud)
并且我抓住了我想要的像素信息,但我很快就完成了这项工作(需要每秒3次或更快),但结果是它主要影响这款基于DirectX的游戏的帧速率.
Python中有没有更快的方法来读取特定的屏幕像素?即使将此限制为每0.3秒运行一次也会造成比实际应用更多的压力(我实际上认为python会比AutoIt 更快用于此特定目的,因此我正在尝试它的原因)
YOU*_*YOU 17
这是PIL的抓取源,它不接受任何参数,它抓住整个屏幕并将其转换为位图.
PyImaging_GrabScreenWin32(PyObject* self, PyObject* args)
{
int width, height;
HBITMAP bitmap;
BITMAPCOREHEADER core;
HDC screen, screen_copy;
PyObject* buffer;
/* step 1: create a memory DC large enough to hold the
entire screen */
screen = CreateDC(";DISPLAY", NULL, NULL, NULL);
screen_copy = CreateCompatibleDC(screen);
width = GetDeviceCaps(screen, HORZRES);
height = GetDeviceCaps(screen, VERTRES);
bitmap = CreateCompatibleBitmap(screen, width, height);
if (!bitmap)
goto error;
if (!SelectObject(screen_copy, bitmap))
goto error;
/* step 2: copy bits into memory DC bitmap */
if (!BitBlt(screen_copy, 0, 0, width, height, screen, 0, 0, SRCCOPY))
goto error;
/* step 3: extract bits from bitmap */
buffer = PyString_FromStringAndSize(NULL, height * ((width*3 + 3) & -4));
if (!buffer)
return NULL;
core.bcSize = sizeof(core);
core.bcWidth = width;
core.bcHeight = height;
core.bcPlanes = 1;
core.bcBitCount = 24;
if (!GetDIBits(screen_copy, bitmap, 0, height, PyString_AS_STRING(buffer),
(BITMAPINFO*) &core, DIB_RGB_COLORS))
goto error;
DeleteObject(bitmap);
DeleteDC(screen_copy);
DeleteDC(screen);
return Py_BuildValue("(ii)N", width, height, buffer);
error:
PyErr_SetString(PyExc_IOError, "screen grab failed");
DeleteDC(screen_copy);
DeleteDC(screen);
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
所以,当我深入一点时,发现C方法很好
http://msdn.microsoft.com/en-us/library/dd144909(VS.85).aspx
Python有ctypes,所以这里是我使用ctypes的方法(在Windows 10中,winnt
已被替换Windows
):
>>> from ctypes import *
>>> user= windll.LoadLibrary("c:\\winnt\\system32\\user32.dll") #I am in windows 2000, may be yours will be windows
>>> h = user.GetDC(0)
>>> gdi= windll.LoadLibrary("c:\\winnt\\system32\\gdi32.dll")
>>> gdi.GetPixel(h,1023,767)
16777215 #I believe its white color of RGB or BGR value, #FFFFFF (according to msdn it should be RGB)
>>> gdi.GetPixel(h,1024,767)
-1 #because my screen is only 1024x768
Run Code Online (Sandbox Code Playgroud)
您可以像这样编写函数GetPixel的包装器
from ctypes import windll
dc= windll.user32.GetDC(0)
def getpixel(x,y):
return windll.gdi32.GetPixel(dc,x,y)
Run Code Online (Sandbox Code Playgroud)
然后你可以使用像getpixel(0,0)
,getpixel(100,0)
等...
PS:我的是Windows 2000,所以我放入winnt
路径,您可能需要将其更改为windows
或者您可以完全删除路径,只需使用user32.dll
并且也gdi32.dll
应该工作.
评论S.Mark的解决方案:user32库已经被windll加载到windll.user32中,所以你可以这样做而不是dc = ...行:
def getpixel(x,y):
return gdi.GetPixel(windll.user32.GetDC(0),x,y)
Run Code Online (Sandbox Code Playgroud)
...或者最好:
dc= windll.user32.GetDC(0)
Run Code Online (Sandbox Code Playgroud)