adding requirements for image menu; integrating area selection with crop and resize functionalities

This commit is contained in:
vb
2025-11-06 16:10:48 +01:00
parent db4fc94385
commit 5aba41a4f9
3 changed files with 176 additions and 13 deletions

View File

@@ -57,6 +57,9 @@ class AreaSelectionHandler:
self._selectionRectangle = None
self._lassoPath = [] # List of canvas coordinates for lasso drawing
self._lassoLine = None # Canvas line item for lasso path
# Pending operation callback (called when selection is completed)
self._pendingOperationCallback = None
def toggle_selection_mode(self) -> None:
"""Toggle interactive selection mode on/off."""
@@ -65,6 +68,7 @@ class AreaSelectionHandler:
self._root.config(cursor="crosshair")
else:
self._root.config(cursor="")
self._pendingOperationCallback = None # Clear pending callback when disabling selection mode
self.clear_selection()
def toggle_selection_shape(self) -> None:
@@ -86,6 +90,44 @@ class AreaSelectionHandler:
if self._selectionArea.is_active and self._selectionArea.is_valid():
self._render_image()
def set_selection_shape(self, shape: str) -> None:
"""Set the selection shape directly.
Args:
shape: One of "rectangle", "circle", or "lasso"
"""
if self._selectionArea is None:
return
if shape in ("rectangle", "circle", "lasso"):
self._selectionArea.set_shape(shape)
self._selectionType = shape
# Enable selection mode if not already enabled
if not self._selectionMode:
self.toggle_selection_mode()
# Refresh selection drawing if active
if self._selectionArea.is_active and self._selectionArea.is_valid():
self._render_image()
def set_rectangular_selection(self) -> None:
"""Set selection to rectangular mode and enable selection."""
self.set_selection_shape("rectangle")
def set_circular_selection(self) -> None:
"""Set selection to circular mode and enable selection."""
self.set_selection_shape("circle")
def set_lasso_selection(self) -> None:
"""Set selection to lasso (free-form) mode and enable selection."""
self.set_selection_shape("lasso")
def set_pending_operation_callback(self, callback: Optional[Callable]) -> None:
"""Set a callback to be executed when a selection is completed.
Args:
callback: Function to call when selection is completed, or None to clear
"""
self._pendingOperationCallback = callback
def on_mouse_click(self, event) -> bool:
"""Handle mouse click for selection.
@@ -212,6 +254,12 @@ class AreaSelectionHandler:
# Redraw the selection highlight to ensure it's visible
self._render_image()
# Check if there's a pending operation callback and execute it
if self._pendingOperationCallback and self._selectionArea.is_valid():
callback = self._pendingOperationCallback
self._pendingOperationCallback = None # Clear callback to prevent multiple calls
callback()
return True
# Handle rectangle/circle mode
@@ -236,6 +284,12 @@ class AreaSelectionHandler:
)
# Redraw the selection highlight to ensure it's visible
self._render_image()
# Check if there's a pending operation callback and execute it
if self._pendingOperationCallback and self._selectionArea.is_valid():
callback = self._pendingOperationCallback
self._pendingOperationCallback = None # Clear callback to prevent multiple calls
callback()
return True
def on_right_click(self, event, get_default_params: Callable) -> bool:
@@ -391,6 +445,56 @@ class AreaSelectionHandler:
# Silently handle errors - crop operation failed
pass
def resize_to_selection_dimensions(self) -> None:
"""Resize the entire image to match the selection area dimensions."""
current_image = self._get_current_image()
if current_image is None or not self._selectionArea or not self._selectionArea.is_active:
return
# Get the selection coordinates
coords = self._selectionArea.get_coordinates()
if not coords:
return
left, top, right, bottom = coords
# Calculate dimensions from selection
width = right - left
height = bottom - top
# Validate dimensions
if width <= 0 or height <= 0:
return
# Get the original image
original_image = current_image.getImage()
if original_image is None:
return
try:
# Take undo snapshot
current_image.snapshot()
# Resize the entire image to the selection dimensions
from utils.image_utils import pil_to_cv2, cv2_to_pil
import cv2
cv_img = pil_to_cv2(original_image)
resized = cv2.resize(cv_img, (int(width), int(height)), interpolation=cv2.INTER_AREA)
resized_image = cv2_to_pil(resized)
# Update the current image
current_image._imageData = resized_image
# Clear selection before re-rendering
self.clear_selection()
# Re-render the image (without selection)
self._render_image()
except Exception as e:
# Silently handle errors - resize operation failed
pass
def apply_manipulation_to_selection(self, manipulation, get_default_params: Callable) -> None:
"""Apply the specified manipulation to the selected area only."""
current_image = self._get_current_image()