147 lines
5.3 KiB
Python
147 lines
5.3 KiB
Python
import numpy as np
|
|
import win32con
|
|
import win32gui
|
|
import win32ui
|
|
from config_file import UserConfigs
|
|
|
|
|
|
class WindowCapture:
|
|
|
|
# properties
|
|
w = 0
|
|
h = 0
|
|
hwnd = None
|
|
cropped_x = 0
|
|
cropped_y = 0
|
|
offset_x = 0
|
|
offset_y = 0
|
|
|
|
# constructor
|
|
def __init__(self, window_name, area, config, coords = 0):
|
|
# find the handle for the window we want to capture.
|
|
# if no window name is given, capture the entire screen
|
|
if window_name is None:
|
|
self.hwnd = win32gui.GetDesktopWindow()
|
|
else:
|
|
self.hwnd = win32gui.FindWindow(None, window_name)
|
|
if not self.hwnd:
|
|
raise Exception('Window not found: {}'.format(window_name))
|
|
|
|
if area == "dig":
|
|
val = config.returnDiggingWindowPos()
|
|
elif area == "magic":
|
|
val = config.returnMagicWindowPos()
|
|
elif area == "dig2":
|
|
val = config.returnDiggingWindowPos2()
|
|
elif area == "equip":
|
|
val = config.returnEquipmentWindowPos()
|
|
elif area == "screen_conf":
|
|
val = config.returnOKWindowPos()
|
|
elif area == "lanes":
|
|
val = coords
|
|
else:
|
|
val = config.returnFullScreenWindowPos()
|
|
|
|
self.w = val[0]
|
|
self.h = val[1]
|
|
self.cropped_x = val[2]
|
|
self.cropped_y = val[3]
|
|
|
|
|
|
|
|
def get_screenshot(self):
|
|
# get the window image data
|
|
wDC = win32gui.GetWindowDC(self.hwnd)
|
|
dcObj = win32ui.CreateDCFromHandle(wDC)
|
|
cDC = dcObj.CreateCompatibleDC()
|
|
dataBitMap = win32ui.CreateBitmap()
|
|
dataBitMap.CreateCompatibleBitmap(dcObj, self.w, self.h)
|
|
cDC.SelectObject(dataBitMap)
|
|
cDC.BitBlt((0, 0), (self.w, self.h), dcObj, (self.cropped_x, self.cropped_y), win32con.SRCCOPY)
|
|
|
|
# convert the raw data into a format opencv can read
|
|
#dataBitMap.SaveBitmapFile(cDC, 'debug.bmp')
|
|
signedIntsArray = dataBitMap.GetBitmapBits(True)
|
|
img = np.fromstring(signedIntsArray, dtype='uint8')
|
|
img.shape = (self.h, self.w, 4)
|
|
|
|
# free resources
|
|
dcObj.DeleteDC()
|
|
cDC.DeleteDC()
|
|
win32gui.ReleaseDC(self.hwnd, wDC)
|
|
win32gui.DeleteObject(dataBitMap.GetHandle())
|
|
|
|
# drop the alpha channel, or cv.matchTemplate() will throw an error like:
|
|
# error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type()
|
|
# && _img.dims() <= 2 in function 'cv::matchTemplate'
|
|
img = img[...,:3]
|
|
|
|
# make image C_CONTIGUOUS to avoid errors that look like:
|
|
# File ... in draw_rectangles
|
|
# TypeError: an integer is required (got type tuple)
|
|
# see the discussion here:
|
|
# https://github.com/opencv/opencv/issues/14866#issuecomment-580207109
|
|
img = np.ascontiguousarray(img)
|
|
|
|
return img
|
|
|
|
def get_screenshot_by_area(self, area):
|
|
|
|
w_local = area[0]
|
|
h_local = area[1]
|
|
cropped_x_local = area[2]
|
|
cropped_y_local = area[3]
|
|
|
|
# get the window image data
|
|
wDC = win32gui.GetWindowDC(self.hwnd)
|
|
dcObj = win32ui.CreateDCFromHandle(wDC)
|
|
cDC = dcObj.CreateCompatibleDC()
|
|
dataBitMap = win32ui.CreateBitmap()
|
|
dataBitMap.CreateCompatibleBitmap(dcObj, w_local, h_local)
|
|
cDC.SelectObject(dataBitMap)
|
|
cDC.BitBlt((0, 0), (w_local, h_local), dcObj, (cropped_x_local, cropped_y_local), win32con.SRCCOPY)
|
|
|
|
# convert the raw data into a format opencv can read
|
|
#dataBitMap.SaveBitmapFile(cDC, 'debug.bmp')
|
|
signedIntsArray = dataBitMap.GetBitmapBits(True)
|
|
img = np.fromstring(signedIntsArray, dtype='uint8')
|
|
img.shape = (h_local, w_local, 4)
|
|
|
|
# free resources
|
|
dcObj.DeleteDC()
|
|
cDC.DeleteDC()
|
|
win32gui.ReleaseDC(self.hwnd, wDC)
|
|
win32gui.DeleteObject(dataBitMap.GetHandle())
|
|
|
|
# drop the alpha channel, or cv.matchTemplate() will throw an error like:
|
|
# error: (-215:Assertion failed) (depth == CV_8U || depth == CV_32F) && type == _templ.type()
|
|
# && _img.dims() <= 2 in function 'cv::matchTemplate'
|
|
img = img[...,:3]
|
|
|
|
# make image C_CONTIGUOUS to avoid errors that look like:
|
|
# File ... in draw_rectangles
|
|
# TypeError: an integer is required (got type tuple)
|
|
# see the discussion here:
|
|
# https://github.com/opencv/opencv/issues/14866#issuecomment-580207109
|
|
img = np.ascontiguousarray(img)
|
|
|
|
return img
|
|
|
|
# find the name of the window you're interested in.
|
|
# once you have it, update window_capture()
|
|
# https://stackoverflow.com/questions/55547940/how-to-get-a-list-of-the-name-of-every-open-window
|
|
@staticmethod
|
|
def list_window_names():
|
|
def winEnumHandler(hwnd, ctx):
|
|
if win32gui.IsWindowVisible(hwnd):
|
|
print(hex(hwnd), win32gui.GetWindowText(hwnd))
|
|
win32gui.EnumWindows(winEnumHandler, None)
|
|
|
|
# translate a pixel position on a screenshot image to a pixel position on the screen.
|
|
# pos = (x, y)
|
|
# WARNING: if you move the window being captured after execution is started, this will
|
|
# return incorrect coordinates, because the window position is only calculated in
|
|
# the __init__ constructor.
|
|
def get_screen_position(self, pos):
|
|
return (pos[0] + self.offset_x, pos[1] + self.offset_y)
|