def save_screenshot():
    hwnd = GetDesktopWindow()
    width = GetSystemMetrics(SM_CXVIRTUALSCREEN)
    height = GetSystemMetrics(SM_CYVIRTUALSCREEN)
    x = GetSystemMetrics(SM_XVIRTUALSCREEN)
    y = GetSystemMetrics(SM_YVIRTUALSCREEN)

    hwnd_dc = GetWindowDC(hwnd)
    mfc_dc = CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()

    save_bit_map = CreateBitmap()
    save_bit_map.CreateCompatibleBitmap(mfc_dc, width, height)
    save_dc.SelectObject(save_bit_map)
    save_dc.BitBlt((0, 0), (width, height), mfc_dc, (x, y), SRCCOPY)

    bmp_info = save_bit_map.GetInfo()
    bmp_str = save_bit_map.GetBitmapBits(True)
    image = Image.frombuffer('RGB',
                             (bmp_info['bmWidth'], bmp_info['bmHeight']),
                             bmp_str, 'raw', 'BGRX', 0, 1)
    time_str = str(ctime()).replace(' ', '_').replace(':', '_').lower()
    name_scr = 'screen_' + time_str + '.png'
    image.save(name_scr, format='png')
    log_record('сохранен скриншот: ' + name_scr)
    save_dc.DeleteDC()
    DeleteObject(save_bit_map.GetHandle())
Beispiel #2
0
    def windowshots(self, x1, y1, x2, y2):
        w, h = x2 - x1, y2 - y1
        # wDC = GetDC(hwnd)
        # 根据窗口句柄获取窗口的设备上下文DC(Divice Context)
        # 获取桌面
        hdesktop = GetDesktopWindow()
        wDC = GetWindowDC(hdesktop)
        # 根据窗口的DC获取dcObj
        dcObj = CreateDCFromHandle(wDC)
        # dcObj创建可兼容的DC
        cDC = dcObj.CreateCompatibleDC()
        # 创建bigmap准备保存图片
        dataBitMap = CreateBitmap()
        # 为bitmap开辟空间
        dataBitMap.CreateCompatibleBitmap(dcObj, w, h)
        # 高度cDC,将截图保存到dataBitMap中
        cDC.SelectObject(dataBitMap)
        # 截取从左上角(0,0)长宽为(w,h)的图片
        cDC.BitBlt((0, 0), (w, h), dcObj, (x1, y1), SRCCOPY)
        # 保存图像
        # dataBitMap.SaveBitmapFile(cDC, 'test.jpg')
        signedIntsArray = dataBitMap.GetBitmapBits(True)
        # Free Resources
        # 释放资源
        DeleteObject(dataBitMap.GetHandle())
        cDC.DeleteDC()
        dcObj.DeleteDC()
        ReleaseDC(hdesktop, wDC)

        screen = np.frombuffer(signedIntsArray, dtype='uint8')
        screen.shape = (h, w, 4)
        screen = cv2.cvtColor(screen, cv2.COLOR_BGRA2BGR)
        return screen
Beispiel #3
0
def screenshot(**kwargs):
    global client

    dimensions = GetWindowDC(client)
    handle = CreateDCFromHandle(dimensions)
    buff = handle.CreateCompatibleDC()

    screenshot = CreateBitmap()
    screenshot.CreateCompatibleBitmap(handle, kwargs['width'],
                                      kwargs['height'])

    buff.SelectObject(screenshot)
    buff.BitBlt((0, 0), (kwargs['width'], kwargs['height']), handle,
                (kwargs['left'], kwargs['top']), SRCCOPY)

    pixels = screenshot.GetBitmapBits(True)
    im = array(
        Image.frombuffer('RGB', (kwargs['width'], kwargs['height']), pixels,
                         'raw', 'BGRX', 0, 1))

    if kwargs['cleaning'] == True:
        im = cleaning(kwargs['width'], kwargs['height'], im)

    handle.DeleteDC()
    buff.DeleteDC()
    ReleaseDC(client, dimensions)
    DeleteObject(screenshot.GetHandle())
    return im
Beispiel #4
0
    def hwd_screenshot(self):
        # 获取句柄窗口的大小信息
        try:
            _left, _top, _right, _bot = self.get_window_rect()
            _width = _right - _left
            _height = _bot - _top
            # 返回句柄窗口的设备环境,覆盖整个窗口,包括非客户区,标题栏,菜单,边框
            _hwnd_dc = GetWindowDC(self.hwnd)
            # 创建设备描述表
            _mfc_dc = CreateDCFromHandle(_hwnd_dc)
            # 创建内存设备描述表
            _save_dc = _mfc_dc.CreateCompatibleDC()
            # 创建位图对象准备保存图片
            _save_bit_map = CreateBitmap()
            # 为bitmap开辟存储空间
            _save_bit_map.CreateCompatibleBitmap(_mfc_dc, _width, _height)
            # 将截图保存到saveBitMap中
            _save_dc.SelectObject(_save_bit_map)
            # 保存bitmap到内存设备描述表
            _save_dc.BitBlt((0, 0), (_width, _height), _mfc_dc, (0, 0),
                            win32con.SRCCOPY)

            # 如果要截图到打印设备:
            ###最后一个int参数:0-保存整个窗口,1-只保存客户区。如果PrintWindow成功函数返回值为1
            # result = windll.user32.PrintWindow(hWnd,_save_dc.GetSafeHdc(),0)
            # print(result) #PrintWindow成功则输出1

            # 保存图像
            ##方法一:windows api保存
            ###保存bitmap到文件
            # _save_bit_map.SaveBitmapFile(_save_dc, "img_Winapi.bmp")

            ##方法二(第一部分):PIL保存
            ###获取位图信息
            # bmpinfo = _save_bit_map.GetInfo()
            # bmpstr = _save_bit_map.GetBitmapBits(True)
            ###生成图像
            # im_PIL = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
            ##方法二(后续转第二部分)

            ##方法三(第一部分):opencv+numpy保存
            ###获取位图信息
            signed_ints_array = _save_bit_map.GetBitmapBits(True)
            return Image.get_img_opencv(signed_ints_array, _width, _height)
            ##方法三(后续转第二部分)
        finally:
            # 内存释放
            DeleteObject(_save_bit_map.GetHandle())
            _save_dc.DeleteDC()
            _mfc_dc.DeleteDC()
            ReleaseDC(self.hwnd, _hwnd_dc)
Beispiel #5
0
 def ScreenShot(self):
     """
     截图 网上找的代码直接复制修改的
     后面加了释放资源代码,网上找的
     """
     hwndDC = GetWindowDC(self.mHwnd)
     mfcDC = CreateDCFromHandle(hwndDC)
     saveDC = mfcDC.CreateCompatibleDC()
     saveBitMap = CreateBitmap()
     saveBitMap.CreateCompatibleBitmap(mfcDC, self.mWindowWidth,
                                       self.mWindowHeight)
     saveDC.SelectObject(saveBitMap)
     saveDC.BitBlt((0, 0), (self.mWindowWidth, self.mWindowHeight), mfcDC,
                   (0, 0), SRCCOPY)
     saveBitMap.SaveBitmapFile(saveDC, self.mScreenShotFileName)
     self.mImageSrc = aircv.imread(self.mScreenShotFileName)
     # release
     DeleteObject(saveBitMap.GetHandle())
     mfcDC.DeleteDC()
     saveDC.DeleteDC()
     ReleaseDC(self.mHwnd, hwndDC)
class SoullessEnv(gym.Env):
    metadata = {'render.modes': ['human']}
    user32 = WinDLL("user32")
    DEATHCOUNT_PATTERN = re.compile("(\d+)")
    KEYS = (KEYS.LEFT, KEYS.RIGHT, KEYS.DELETE)
    TRANSITION_TO_ACTION = {"10": "UP", "01": "DOWN", "00": False, "11": False}

    def __init__(self):
        self.AHK = AHK()
        self.application = self.start_game()
        self.process_id = self.application.process
        self.process = Process(pid=self.process_id)
        self.dialog = self.get_window_dialog()
        self.handle = self.dialog.handle
        self.window = Window.from_pid(self.AHK, self.process_id)

        left, top, right, bot = GetClientRect(self.handle)
        w = right - left
        h = bot - top

        self.hwndDC = GetWindowDC(self.handle)
        self.mfcDC = CreateDCFromHandle(self.hwndDC)
        self.saveDC = self.mfcDC.CreateCompatibleDC()
        self.saveDC_handle = self.saveDC.GetSafeHdc()

        self.saveBitMap = CreateBitmap()
        self.saveBitMap.CreateCompatibleBitmap(self.mfcDC, w, h)
        self.bmpinfo = self.saveBitMap.GetInfo()
        self.saveDC.SelectObject(self.saveBitMap)

        self.navigate_main_menu()
        self.enter_avoidance()
        self.process.suspend()

        self.PREVIOUS_ACTION = 0
        self.deathcount = self.get_game_deathcount()
        self.action_space = spaces.Discrete(6)
        self.elapsed_time = 0.0

        self.observation_space = spaces.Dict({"window":
                                                  spaces.Box(low=0, high=255, shape=self.get_observation_space_size(),
                                                             dtype=np.uint8),
                                              "time": spaces.Box(low=0, high=900, shape=(1,))})

    def start_game(self):
        """starts the Soulless process"""
        app = Application().start(
            "D:/Users/david/PycharmProjects/reinforcement-learning/gym-soulless/Soulless 1.3HM/Soulless Hard Mode.exe")
        return app

    def get_window_dialog(self):
        """:returns the main dialog of the application, which is the entry-point for interacting with it"""
        return self._top_window()

    @try_loop(error_type=RuntimeError)
    def _top_window(self):
        return self.application.top_window()

    def navigate_main_menu(self):
        """from the title screen it navigates the menus until it enters the game"""
        self.window.send("{Shift}", blocking=False)
        sleep(3)
        self.window.send("{Shift}", blocking=False)

    def enter_avoidance(self):
        self.window.send("{Left down}", blocking=False)
        sleep(0.3)
        self.window.send("{Left up}", blocking=False)
        sleep(2)

    def capture_window(self):
        """:returns a np array image of the dialog cropped to exclude the margins for resizing the window
        https://stackoverflow.com/questions/19695214/python-screenshot-of-inactive-window-printwindow-win32gui"""

        SoullessEnv.user32.PrintWindow(HWND(self.handle), self.saveDC_handle, 3)
        bmpstr = self.saveBitMap.GetBitmapBits(True)

        im = Image.frombuffer(
            'RGB',
            (self.bmpinfo['bmWidth'], self.bmpinfo['bmHeight']),
            bmpstr, 'raw', 'BGRX', 0, 1)
        return np.array(im, copy=False)

    def step(self, action: int):
        """expects the game to be in a suspended state"""
        is_done, obs, reward = self.step_and_track_elapsed_time(action)
        obs = {"window": obs, "time": np.array([self.elapsed_time], dtype=np.float)}
        return obs, reward, is_done, {}

    def step_and_track_elapsed_time(self, action):
        self.process.resume()
        step_start_time = perf_counter()
        is_done, obs = self._step(action)
        self.process.suspend()
        step_end_time = perf_counter()
        elapsed_time = step_end_time - step_start_time
        self.elapsed_time += elapsed_time
        return is_done, obs, elapsed_time

    def _step(self, action):
        self.perform_action(action)
        obs = self.capture_window()
        is_done = self.is_done()
        if is_done:
            self.update_env_deathcount()
        return is_done, obs

    def perform_action(self, action):
        keystrokes = self.get_action_transition(self.PREVIOUS_ACTION, action)
        self.send_input_to_game(keystrokes)
        self.PREVIOUS_ACTION = action

    def is_done(self):
        return self.get_game_deathcount() > self.deathcount

    def update_env_deathcount(self):
        self.deathcount = self.get_game_deathcount()

    def get_action_transition(self, old_action: int, new_action: int):
        """:param old_action is the action performed on the previous step, or no-op if this is the first step
        :param new_action is the action performed on this step
        :returns the input to the send function needed to transition from the old action to the new action"""

        old_action, new_action = bin(old_action)[2:].zfill(3), bin(new_action)[2:].zfill(3)
        actions = map(SoullessEnv.TRANSITION_TO_ACTION.get, map("".join, zip(old_action, new_action)))

        return "".join(getattr(key, action) for key, action in zip(SoullessEnv.KEYS, actions) if action)

    def send_input_to_game(self, keystrokes: str):
        """:param keystrokes is the input to the send_keys function"""
        self.window.send(keystrokes, blocking=False)

    def reset(self):
        self.process.resume()
        self.window.send("r", delay=150)
        self.process.suspend()
        self.elapsed_time = 0.0

        return {"window": self.capture_window(), "time": np.array([self.elapsed_time], dtype=np.float)}

    def render(self, mode='human'):
        pass

    def close(self):
        DeleteObject(self.saveBitMap.GetHandle())
        self.saveDC.DeleteDC()
        self.mfcDC.DeleteDC()
        ReleaseDC(self.handle, self.hwndDC)
        self.application.kill()

    def get_observation_space_size(self):
        return self.capture_window().shape

    def get_game_deathcount(self):
        """:returns the number of times the kid has died"""
        title = self.window.title.decode("utf8")
        return int(re.search(SoullessEnv.DEATHCOUNT_PATTERN, title)[0])