Skip to content

Instantly share code, notes, and snippets.

@dustinandrews
Last active June 14, 2017 18:26
Show Gist options
  • Save dustinandrews/d06a9430a435f42e0a05c0491e9e9d4a to your computer and use it in GitHub Desktop.
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.
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