import logging import cv2 import math import win32gui from win32api import GetSystemMetrics import imutils import numpy as np import pywintypes from PIL import ImageGrab from fishy.systems.globals import G class Window: """ Records the game window, and allows to create instance to process it """ Screen = None windowOffset = None titleOffset = None hwnd = None showing = False def __init__(self, crop=None, color=None, scale=None): """ create a window instance with these pre process :param crop: [x1,y1,x2,y2] array defining the boundaries to crop :param color: color to use example cv2.COLOR_RGB2HSV :param scale: scaling the window """ self.color = color self.crop = crop self.scale = scale @staticmethod def Init(): """ Executed once before the main loop, Finds the game window, and calculates the offset to remove the title bar """ try: Window.hwnd = win32gui.FindWindow(None, "Elder Scrolls Online") rect = win32gui.GetWindowRect(Window.hwnd) clientRect = win32gui.GetClientRect(Window.hwnd) Window.windowOffset = math.floor(((rect[2] - rect[0]) - clientRect[2]) / 2) Window.titleOffset = ((rect[3] - rect[1]) - clientRect[3]) - Window.windowOffset if G.arguments["--borderless"]: Window.titleOffset = 0 except pywintypes.error: logging.info("Game window not found") quit() @staticmethod def Loop(): """ Executed in the start of the main loop finds the game window location and captures it """ Window.showing = False bbox = (0, 0, GetSystemMetrics(0), GetSystemMetrics(1)) tempScreen = np.array(ImageGrab.grab(bbox=bbox)) tempScreen = cv2.cvtColor(tempScreen, cv2.COLOR_BGR2RGB) rect = win32gui.GetWindowRect(Window.hwnd) crop = (rect[0] + Window.windowOffset, rect[1] + Window.titleOffset, rect[2] - Window.windowOffset, rect[3] - Window.windowOffset) Window.Screen = tempScreen[crop[1]:crop[3], crop[0]:crop[2]] if Window.Screen.size == 0: logging.info("Don't minimize or drag game window outside the screen") quit(1) @staticmethod def LoopEnd(): """ Executed in the end of the game loop """ cv2.waitKey(25) if not Window.showing: cv2.destroyAllWindows() def getCapture(self): """ copies the recorded screen and then pre processes its :return: game window image """ temp_img = Window.Screen if self.color is not None: temp_img = cv2.cvtColor(temp_img, self.color) if self.crop is not None: temp_img = temp_img[self.crop[1]:self.crop[3], self.crop[0]:self.crop[2]] if self.scale is not None: temp_img = cv2.resize(temp_img, (self.scale[0], self.scale[1]), interpolation=cv2.INTER_AREA) return temp_img def processedImage(self, func=None): """ processes the image using the function provided :param func: function to process image :return: processed image """ if func is None: return self.getCapture() else: return func(self.getCapture()) def show(self, name, resize=None, func=None): """ Displays the processed image for debugging purposes :param name: unique name for the image, used to create a new window :param resize: scale the image to make small images more visible :param func: function to process the image """ img = self.processedImage(func) if resize is not None: img = imutils.resize(img, width=resize) cv2.imshow(name, img) Window.showing = True