diff --git a/src/df_tools/dfwindow.py b/src/df_tools/dfwindow.py index f5c321b..2b0e984 100644 --- a/src/df_tools/dfwindow.py +++ b/src/df_tools/dfwindow.py @@ -1,4 +1,5 @@ import json +import math import time from pathlib import Path @@ -163,6 +164,14 @@ class DFWINDOW: @property def maxGridY(self) -> int: return self._gridy_max + + @property + def gridHeight(self) -> int: + return int(self._gridy_max + 1) + + @property + def gridWidth(self) -> int: + return int(self._gridx_max + 1) @property def stepSizeX(self) -> int: @@ -211,16 +220,17 @@ class DFWINDOW: thekey: str | int, count: int = 1, modifier: str | int | list[str | int] | None = None, - cycle_delay: float = 0.1, + cycle_delay: float = 9999, sub_cycle_delay: float = 0.05, custom_lookup: dict[str, int] | None = None, ): + _cycle_delay = cycle_delay if cycle_delay != 9999 else self.sleep_after_key self.focusWindow() _sendKey( thekey=thekey, count=count, modifier=modifier, - cycle_delay=self.sleep_after_key, + cycle_delay=_cycle_delay, sub_cycle_delay=sub_cycle_delay, custom_lookup=custom_lookup, ) @@ -324,7 +334,7 @@ class DFWINDOW: # We now know how many steps the map is vertically steps_vertical = steps_down - logger.debug(f"Map is about {steps_vertical} steps vertical. Current step is {steps_down}") + logger.debug(f"Map is about {steps_vertical+1} steps vertical. Current index is {steps_down}") # go right until the left map edge disappears while self.TOOLS.isLeftBorder(img): @@ -348,7 +358,7 @@ class DFWINDOW: # And those are the horrizontal steps steps_horrizontal = steps_right - logger.debug(f"Map is about {steps_horrizontal} steps horrizontal. Current step is {steps_right}") + logger.debug(f"Map is about {steps_horrizontal+1} steps horrizontal. Current index is {steps_right}") self._gridx_max = steps_horrizontal self._gridy_max = steps_vertical @@ -385,10 +395,12 @@ class DFWINDOW: # (max*size) is too far, so we subract the ofset/border from the right map edge self._map_width = ( - (img.shape[1] - cal_left_border) # Grid x = 0 + (self.contentWidth - cal_left_border) # Grid x = 0 + ((self._gridx_max - 1) * self._step_size_x) # All the middle + cal_right_border # grid x = max ) + logger.trace(f"|{self.contentWidth} - {cal_left_border}|({self._gridx_max} - 1) * {self._step_size_x}|{cal_right_border}|") + logger.trace(f"{self._map_width} = |{self.contentWidth - cal_left_border}|{(self._gridx_max - 1) * self._step_size_x}|{cal_right_border}|") self._map_height = ( (img.shape[0] - cal_top_border) # Grid x = 0 @@ -400,8 +412,8 @@ class DFWINDOW: logger.debug(f"Map dimensions calculated as {self._map_width} x {self._map_height}") - logger.info( - f"Grid calibration complete. Grid steps ({self._gridy_max + 1},{self._gridy_max + 1}), step sizes({self._step_size_x},{self._step_size_y})" + logger.debug( + f"Grid calibration complete. Grid steps ({self._gridx_max + 1},{self._gridy_max + 1}), step sizes({self._step_size_x},{self._step_size_y})" ) def test1(self): @@ -479,7 +491,118 @@ class DFWINDOW: self._map_height = calib_info["map_height"] self._map_width = calib_info["map_width"] + def addToCanvas(self, tile, x: int, y: int) -> tuple[int, int]: + # calculate safe (in bounds) abs pos of far end + safe_farx = min(x + tile.shape[1], self.map_canvas.shape[1]) + safe_fary = min(y + tile.shape[0], self.map_canvas.shape[0]) + + safe_width = safe_farx - x + safe_height = safe_fary - y + + self.map_canvas[y:safe_fary, x:safe_farx] = tile[: (safe_fary - y), : (safe_farx - x)] + logger.trace(f"Added {safe_width}x{safe_height} of tile ({tile.shape[1]}x{tile.shape[0]}) at {x},{y} ") + + return (int(safe_width), int(safe_height)) + def getPanoramaMap(self): self.calibrateGrid() + # Create the big_map canvas + canvas_width = self.contentWidth + (self.stepSizeX * (self.maxGridX + 1 + 1)) + canvas_height = self.contentHeight + (self.stepSizeY * (self.maxGridY + 1 + 1)) + + self.map_canvas = np.zeros((canvas_height, canvas_width, 4), dtype=np.uint8) + + # We want to cap from the content area, minus and black borders. + # starting at canvas_pos of 0,0 Add cap to the canvas + # Then we pan down almost enough to push everything up off the screen + # Then we cap the new stuff, row starting at max(firstNotBlackY, contentHeight - (amount we paned down)) + # at canvas_pos add cap to canvas + # increase canvas_pos.y by that new amount + # if we already have a bottom bar, or we are at last grid, break out, otherwise loop + + if 1 == 1: + # The initial setup + new_x = self.contentWidth + new_y = self.contentHeight + canvas_pos = [0, 0] + self.setGridPos(0, 0) + + # Never do more than this many loops + sanity_steps_left = self.maxGridY + 1 + while sanity_steps_left > 0: + # Capture a tile + img = self.capContent() + cap_start_x = max(self.TOOLS.firstNotBlackX(img), self.contentWidth - new_x) + cap_start_y = max(self.TOOLS.firstNotBlackY(img), self.contentHeight - new_y) + + # use min with other restriction if needed in the future min(lastNotBlack,Other_limit) + cap_end_x = self.TOOLS.lastNotBlackX(img) + cap_end_y = self.TOOLS.lastNotBlackY(img) + + pixels_added = self.addToCanvas( + img[cap_start_y : cap_end_y + 1, cap_start_x : cap_end_x + 1], canvas_pos[0], canvas_pos[1] + ) + canvas_pos[1] += pixels_added[1] + + # Reasons to finish this column: + # - pixels_added[1] < cap_height + # - (with cur logic) cap_height < self.contentHeight + # - self.curGridY >= self.maxGridY + logger.trace(f"{cap_start_y=} {cap_end_y=} {self.contentHeight=} {pixels_added=} {canvas_pos=}") + logger.trace(f"{self.curGridPos=} {self.map_canvas.shape=}") + + sanity_steps_left -= 1 # Prevent runaway loops + + if not ( + (cap_end_y + 1 < self.contentHeight) + or (pixels_added[1] < ((cap_end_y + 1) - cap_start_y)) + or (self.curGridY >= self.maxGridY) + or (canvas_pos[1] >= self.map_canvas.shape[0]) + ): + # pan down for more map, but watch limits + steps_to_pan_down = min(self.maxGridY - self.curGridY, math.floor(self.contentHeight / self.stepSizeY)) + self.setGridPos(0, self.curGridY + steps_to_pan_down) + new_y = steps_to_pan_down * self.stepSizeY + else: + break + + if sanity_steps_left < 1: + logger.debug(f"Our loop in the Y axis ran over. {sanity_steps_left=}") + + if self.map_canvas is not None: + cv2.imwrite("./test_canvas.png", self.map_canvas) + + # if 1 == 0: + # self.setGridPos(0, 0) + # canvas_x = 0 + # canvas_y = 0 + + # img = self.capContent() + # startx = self.TOOLS.firstNotBlackX(img) + # starty = self.TOOLS.firstNotBlackY(img) + # img_ul = img[starty:, startx:] + # # cv2.rectangle(img, (startx, starty), (self.contentWidth, self.contentHeight), (255, 255, 255, 255), 3) + # logger.debug(f"img_ul is {img_ul.shape[1]} x {img_ul.shape[0]}") + + # last_add = self.addToCanvas(img_ul, 0, 0) + + # steps_to_pan_down = math.floor(self.contentHeight / self.stepSizeY) + # logger.debug(f"{startx=} {starty=} {steps_to_pan_down=}") + # self.setGridPos(0, steps_to_pan_down) + # time.sleep(self.sleep_after_panning) + # img = self.capContent() + + # new_starty = self.contentHeight - (steps_to_pan_down * self.stepSizeY) + # img_next = img[new_starty:, startx:] + # logger.debug(f"img_next is {img_next.shape[1]} x {img_next.shape[0]}") + # # cv2.rectangle(img, (startx, new_starty), (self.contentWidth, self.contentHeight), (255, 0, 0), 3) + + # self.addToCanvas(img_next, 0, last_add[1]) + # cv2.imwrite("./test_canvas.png", self.map_canvas) + # a = 1 + # logger.debug(f"{new_starty=}") + + logger.debug("place to break") + return None diff --git a/src/df_tools/imgtools.py b/src/df_tools/imgtools.py index 7553005..8e13a82 100644 --- a/src/df_tools/imgtools.py +++ b/src/df_tools/imgtools.py @@ -559,6 +559,7 @@ def test5(): if __name__ == "__main__": - setup_logging(level="DEBUG", enqueue=False, console_show_time=False, console_tracebacks=True) + # level 5 is TRACE + setup_logging(level=5, enqueue=False, console_show_time=False, console_tracebacks=True) test5()