creatumlibre.ui.manager.image_handler
1# pylint: disable=no-member 2 3import cv2 4import numpy as np 5from PyQt6.QtGui import QImage, QPixmap 6 7from creatumlibre.graphics.selection.region_manager import RegionManager 8from creatumlibre.ui.mode.ui_input_mode import TransformMode 9 10 11class ImageHandler: 12 """Handles a single image object: pixel data, selection, and position.""" 13 14 def __init__(self, image_array: np.ndarray, position=(0, 0), is_promoted=False): 15 self.original_image = image_array # BGR format 16 self.position = position # Absolute position in scene (e.g., top-left) 17 self.position_before_drag = position # reference to add dx,dy while dragging 18 self.is_promoted = is_promoted 19 self.is_selected = False 20 self.region_manager = RegionManager() 21 self.region_manager.initialize_mask(self.original_image.shape) 22 23 def copy(self): 24 new = ImageHandler(self.original_image.copy()) 25 new.position = self.position # Assuming it's immutable (like a tuple) 26 new.is_promoted = False 27 new.is_selected = False 28 new.region_manager = self.region_manager.copy() 29 return new 30 31 def get_image(self) -> np.ndarray: 32 """Returns the raw image array.""" 33 return self.original_image 34 35 def contains_point(self, click_position: tuple[int, int]) -> bool: 36 """hit test in object coordinates""" 37 x, y = click_position 38 px, py = self.get_position() 39 h, w = self.original_image.shape[:2] 40 return px <= x <= px + w and py <= y <= py + h 41 42 def get_pixmap(self) -> QPixmap: 43 """Converts the image array (BGR) to a QPixmap for UI display.""" 44 image = self.get_image() 45 rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 46 height, width, channels = rgb_image.shape 47 bytes_per_line = channels * width 48 49 q_image = QImage( 50 rgb_image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888 51 ) 52 return QPixmap.fromImage(q_image) 53 54 def set_image(self, image): 55 self.original_image = image 56 57 def set_position(self, position: tuple): 58 """set global position""" 59 self.position = position 60 61 def get_position(self) -> tuple: 62 """Returns the (x, y) position in global scene space.""" 63 return self.position 64 65 def get_mask(self) -> np.ndarray: 66 """Returns the current alpha mask (0-255).""" 67 return self.region_manager.mask 68 69 def extract_selection_as_new_image(self) -> "ImageHandler | None": 70 """Extracts the currently selected region as a new ImageHandler instance.""" 71 selection_mask = self.region_manager.get_mask() 72 if selection_mask is None: 73 return None 74 75 x, y, w, h = self.region_manager.get_bounding_rect() 76 77 # Clip region safely from image 78 selected_region = self.original_image[y : y + h, x : x + w].copy() 79 80 # Optional: clip selection mask too 81 # cropped_mask = selection_mask[y:y+h, x:x+w].copy() 82 83 new_object = ImageHandler( 84 image_array=selected_region, position=(x, y), is_promoted=True 85 ) 86 87 return new_object 88 89 def draw_selection_frame( 90 self, transform_mode: TransformMode, zoom_factor: float = 1.0 91 ): 92 """Draws a selection frame with optional handles on this image.""" 93 img = self.original_image 94 h, w = img.shape[:2] 95 if h < 4 or w < 4: 96 return 97 color = (255, 0, 255) # magenta 98 thickness = int(1 / zoom_factor) 99 100 # Draw border 101 cv2.rectangle(img, (0, 0), (w - 1, h - 1), color, thickness) 102 print(transform_mode) 103 104 # Add 9-resize handles, rotate pivot, etc. 105 # For example, draw corner point: 106 # cv2.circle(img, (0, 0), radius=4, color=color, thickness=-1)
class
ImageHandler:
12class ImageHandler: 13 """Handles a single image object: pixel data, selection, and position.""" 14 15 def __init__(self, image_array: np.ndarray, position=(0, 0), is_promoted=False): 16 self.original_image = image_array # BGR format 17 self.position = position # Absolute position in scene (e.g., top-left) 18 self.position_before_drag = position # reference to add dx,dy while dragging 19 self.is_promoted = is_promoted 20 self.is_selected = False 21 self.region_manager = RegionManager() 22 self.region_manager.initialize_mask(self.original_image.shape) 23 24 def copy(self): 25 new = ImageHandler(self.original_image.copy()) 26 new.position = self.position # Assuming it's immutable (like a tuple) 27 new.is_promoted = False 28 new.is_selected = False 29 new.region_manager = self.region_manager.copy() 30 return new 31 32 def get_image(self) -> np.ndarray: 33 """Returns the raw image array.""" 34 return self.original_image 35 36 def contains_point(self, click_position: tuple[int, int]) -> bool: 37 """hit test in object coordinates""" 38 x, y = click_position 39 px, py = self.get_position() 40 h, w = self.original_image.shape[:2] 41 return px <= x <= px + w and py <= y <= py + h 42 43 def get_pixmap(self) -> QPixmap: 44 """Converts the image array (BGR) to a QPixmap for UI display.""" 45 image = self.get_image() 46 rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 47 height, width, channels = rgb_image.shape 48 bytes_per_line = channels * width 49 50 q_image = QImage( 51 rgb_image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888 52 ) 53 return QPixmap.fromImage(q_image) 54 55 def set_image(self, image): 56 self.original_image = image 57 58 def set_position(self, position: tuple): 59 """set global position""" 60 self.position = position 61 62 def get_position(self) -> tuple: 63 """Returns the (x, y) position in global scene space.""" 64 return self.position 65 66 def get_mask(self) -> np.ndarray: 67 """Returns the current alpha mask (0-255).""" 68 return self.region_manager.mask 69 70 def extract_selection_as_new_image(self) -> "ImageHandler | None": 71 """Extracts the currently selected region as a new ImageHandler instance.""" 72 selection_mask = self.region_manager.get_mask() 73 if selection_mask is None: 74 return None 75 76 x, y, w, h = self.region_manager.get_bounding_rect() 77 78 # Clip region safely from image 79 selected_region = self.original_image[y : y + h, x : x + w].copy() 80 81 # Optional: clip selection mask too 82 # cropped_mask = selection_mask[y:y+h, x:x+w].copy() 83 84 new_object = ImageHandler( 85 image_array=selected_region, position=(x, y), is_promoted=True 86 ) 87 88 return new_object 89 90 def draw_selection_frame( 91 self, transform_mode: TransformMode, zoom_factor: float = 1.0 92 ): 93 """Draws a selection frame with optional handles on this image.""" 94 img = self.original_image 95 h, w = img.shape[:2] 96 if h < 4 or w < 4: 97 return 98 color = (255, 0, 255) # magenta 99 thickness = int(1 / zoom_factor) 100 101 # Draw border 102 cv2.rectangle(img, (0, 0), (w - 1, h - 1), color, thickness) 103 print(transform_mode) 104 105 # Add 9-resize handles, rotate pivot, etc. 106 # For example, draw corner point: 107 # cv2.circle(img, (0, 0), radius=4, color=color, thickness=-1)
Handles a single image object: pixel data, selection, and position.
ImageHandler(image_array: numpy.ndarray, position=(0, 0), is_promoted=False)
15 def __init__(self, image_array: np.ndarray, position=(0, 0), is_promoted=False): 16 self.original_image = image_array # BGR format 17 self.position = position # Absolute position in scene (e.g., top-left) 18 self.position_before_drag = position # reference to add dx,dy while dragging 19 self.is_promoted = is_promoted 20 self.is_selected = False 21 self.region_manager = RegionManager() 22 self.region_manager.initialize_mask(self.original_image.shape)
def
get_image(self) -> numpy.ndarray:
32 def get_image(self) -> np.ndarray: 33 """Returns the raw image array.""" 34 return self.original_image
Returns the raw image array.
def
contains_point(self, click_position: tuple[int, int]) -> bool:
36 def contains_point(self, click_position: tuple[int, int]) -> bool: 37 """hit test in object coordinates""" 38 x, y = click_position 39 px, py = self.get_position() 40 h, w = self.original_image.shape[:2] 41 return px <= x <= px + w and py <= y <= py + h
hit test in object coordinates
def
get_pixmap(self) -> PyQt6.QtGui.QPixmap:
43 def get_pixmap(self) -> QPixmap: 44 """Converts the image array (BGR) to a QPixmap for UI display.""" 45 image = self.get_image() 46 rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 47 height, width, channels = rgb_image.shape 48 bytes_per_line = channels * width 49 50 q_image = QImage( 51 rgb_image.data, width, height, bytes_per_line, QImage.Format.Format_RGB888 52 ) 53 return QPixmap.fromImage(q_image)
Converts the image array (BGR) to a QPixmap for UI display.
def
set_position(self, position: tuple):
58 def set_position(self, position: tuple): 59 """set global position""" 60 self.position = position
set global position
def
get_position(self) -> tuple:
62 def get_position(self) -> tuple: 63 """Returns the (x, y) position in global scene space.""" 64 return self.position
Returns the (x, y) position in global scene space.
def
get_mask(self) -> numpy.ndarray:
66 def get_mask(self) -> np.ndarray: 67 """Returns the current alpha mask (0-255).""" 68 return self.region_manager.mask
Returns the current alpha mask (0-255).
70 def extract_selection_as_new_image(self) -> "ImageHandler | None": 71 """Extracts the currently selected region as a new ImageHandler instance.""" 72 selection_mask = self.region_manager.get_mask() 73 if selection_mask is None: 74 return None 75 76 x, y, w, h = self.region_manager.get_bounding_rect() 77 78 # Clip region safely from image 79 selected_region = self.original_image[y : y + h, x : x + w].copy() 80 81 # Optional: clip selection mask too 82 # cropped_mask = selection_mask[y:y+h, x:x+w].copy() 83 84 new_object = ImageHandler( 85 image_array=selected_region, position=(x, y), is_promoted=True 86 ) 87 88 return new_object
Extracts the currently selected region as a new ImageHandler instance.
def
draw_selection_frame( self, transform_mode: creatumlibre.ui.mode.ui_input_mode.TransformMode, zoom_factor: float = 1.0):
90 def draw_selection_frame( 91 self, transform_mode: TransformMode, zoom_factor: float = 1.0 92 ): 93 """Draws a selection frame with optional handles on this image.""" 94 img = self.original_image 95 h, w = img.shape[:2] 96 if h < 4 or w < 4: 97 return 98 color = (255, 0, 255) # magenta 99 thickness = int(1 / zoom_factor) 100 101 # Draw border 102 cv2.rectangle(img, (0, 0), (w - 1, h - 1), color, thickness) 103 print(transform_mode) 104 105 # Add 9-resize handles, rotate pivot, etc. 106 # For example, draw corner point: 107 # cv2.circle(img, (0, 0), radius=4, color=color, thickness=-1)
Draws a selection frame with optional handles on this image.