Last active
June 14, 2017 18:26
-
-
Save dustinandrews/d06a9430a435f42e0a05c0491e9e9d4a to your computer and use it in GitHub Desktop.
A fast way to use win32ui and win32gui to capture screens from applications in Microsoft Windows and scale them using StretchBlt.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import win32ui | |
import win32gui | |
import win32con | |
import numpy as np | |
from matplotlib import pyplot as plt | |
""" | |
Search open windows programs for a title containing the search_str | |
and set hwnd | |
""" | |
search_str = 'Game' | |
global hwnd | |
hwnd = None | |
def enumHandler(h, lParam): | |
global hwnd | |
if win32gui.IsWindowVisible(h): | |
if search_str in win32gui.GetWindowText(h): | |
hwnd = h | |
print("Found window handle: {}".format(h)) | |
win32gui.EnumWindows(enumHandler, None) | |
#%% | |
""" | |
Get the window dimensions | |
""" | |
l,t,r,b=win32gui.GetWindowRect(hwnd) | |
h=b-t | |
w=r-l | |
""" | |
Set the size of the captured image to the scaling factor | |
""" | |
scaling = 0.5 | |
dest_h = int(h * scaling) | |
dest_w = int(w * scaling) | |
""" | |
Create all the win32 objects needed to do the copy operation | |
""" | |
dataBitMap = win32ui.CreateBitmap() | |
w_handle_DC = win32gui.GetWindowDC(hwnd) | |
windowDC = win32ui.CreateDCFromHandle(w_handle_DC) | |
memDC = windowDC.CreateCompatibleDC() | |
dataBitMap.CreateCompatibleBitmap(windowDC , dest_w, dest_h) | |
memDC.SelectObject(dataBitMap) | |
""" | |
Use the windows api to capture and scale an image of the window | |
""" | |
def getScaled(dest_w, dest_h): | |
memDC.StretchBlt((0,0), (dest_w,dest_h), windowDC, (0,0), (w,h), win32con.SRCCOPY) | |
""" | |
dataBitMap.GetBitmapBits(False) returns a tuple | |
dataBitMpa.GetBitmapBits(True) returns a string of encoded binary | |
values. | |
%timeit bits = np.array(dataBitMap.GetBitmapBits(False), np.uint8) | |
118 ms ± 21.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) | |
%timeit bits = np.fromstring(dataBitMap.GetBitmapBits(True), np.uint8) | |
2.21 ms ± 469 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) | |
""" | |
bits = np.fromstring(dataBitMap.GetBitmapBits(True), np.uint8) | |
""" | |
%timeit rgba = bits.reshape(dest_h, dest_w,4).transpose() | |
901 ns ± 344 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) | |
%timeit r,g,b = bits[0::4].reshape(dest_h, dest_w), bits[1::4].reshape(dest_h, dest_w), bits[2::4].reshape(dest_h, dest_w) | |
3.59 µs ± 1.39 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each) | |
""" | |
# GetBitMapBits returns G,B,R,A,G,B,R,A ... over the pixels | |
r,g,b = bits[2::4].reshape(dest_h, dest_w), bits[1::4].reshape(dest_h, dest_w), bits[0::4].reshape(dest_h, dest_w) | |
return r,g,b | |
r,g,b = getScaled(dest_w, dest_h) | |
fig = plt.figure(1) | |
plt.subplot(131) | |
plt.imshow(r, 'Reds') | |
plt.subplot(132) | |
plt.imshow(g, 'Greens') | |
plt.subplot(133) | |
plt.imshow(b, 'Blues') | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment