fixing cropping coordinates
This commit is contained in:
115
src/GUI.py
115
src/GUI.py
@@ -371,15 +371,24 @@ class GUI:
|
||||
selection_coords["left"], selection_coords["top"],
|
||||
selection_coords["right"], selection_coords["bottom"]
|
||||
)
|
||||
# Redraw the selection highlight to ensure it's visible
|
||||
self._renderCurrentImage()
|
||||
|
||||
def _onRightClick(self, event) -> None:
|
||||
"""Handle right-click to show context menu for manipulation options."""
|
||||
if not self._selectionArea.is_active or not self._selectionArea.is_valid():
|
||||
if not self._selectionArea or not self._selectionArea.is_active:
|
||||
return
|
||||
|
||||
if not self._selectionArea.is_valid():
|
||||
return
|
||||
|
||||
# Create context menu with all available manipulations
|
||||
context_menu = tk.Menu(self._root, tearoff=0)
|
||||
|
||||
# Add crop to selection option first (most common use case)
|
||||
context_menu.add_command(label="Crop to Selection", command=self._cropToSelection)
|
||||
context_menu.add_separator()
|
||||
|
||||
# Add manipulation options
|
||||
manipulations = GetImageManipulationList()
|
||||
for manipulation in manipulations:
|
||||
@@ -407,25 +416,37 @@ class GUI:
|
||||
if pil_image is None:
|
||||
return None
|
||||
|
||||
# Convert widget coordinates to canvas coordinates (accounts for borders/scroll)
|
||||
canvas_x1 = self._imageCanvas.canvasx(start_x)
|
||||
canvas_y1 = self._imageCanvas.canvasy(start_y)
|
||||
canvas_x2 = self._imageCanvas.canvasx(end_x)
|
||||
canvas_y2 = self._imageCanvas.canvasy(end_y)
|
||||
|
||||
# Get image dimensions
|
||||
img_width, img_height = pil_image.size
|
||||
|
||||
# Get canvas dimensions
|
||||
canvas_width = self._imageCanvas.winfo_width()
|
||||
canvas_height = self._imageCanvas.winfo_height()
|
||||
# Get canvas dimensions for scaling
|
||||
# Use stored canvas image dimensions if available (from when image was rendered)
|
||||
if self._canvasImageWidth and self._canvasImageHeight:
|
||||
canvas_width = self._canvasImageWidth
|
||||
canvas_height = self._canvasImageHeight
|
||||
else:
|
||||
# Fallback: use actual canvas widget dimensions
|
||||
canvas_width = self._imageCanvas.winfo_width()
|
||||
canvas_height = self._imageCanvas.winfo_height()
|
||||
|
||||
if canvas_width <= 0 or canvas_height <= 0:
|
||||
return None
|
||||
|
||||
if canvas_width <= 0 or canvas_height <= 0:
|
||||
return None
|
||||
|
||||
# Calculate scaling factors
|
||||
# Calculate scaling factors to convert canvas coordinates to image coordinates
|
||||
scale_x = img_width / canvas_width
|
||||
scale_y = img_height / canvas_height
|
||||
|
||||
# Convert coordinates
|
||||
left = int(min(start_x, end_x) * scale_x)
|
||||
top = int(min(start_y, end_y) * scale_y)
|
||||
right = int(max(start_x, end_x) * scale_x)
|
||||
bottom = int(max(start_y, end_y) * scale_y)
|
||||
# Convert canvas coordinates to image coordinates
|
||||
left = int(min(canvas_x1, canvas_x2) * scale_x)
|
||||
top = int(min(canvas_y1, canvas_y2) * scale_y)
|
||||
right = int(max(canvas_x1, canvas_x2) * scale_x)
|
||||
bottom = int(max(canvas_y1, canvas_y2) * scale_y)
|
||||
|
||||
# Ensure coordinates are within image bounds
|
||||
left = max(0, min(left, img_width))
|
||||
@@ -439,6 +460,58 @@ class GUI:
|
||||
|
||||
return None
|
||||
|
||||
def _cropToSelection(self) -> None:
|
||||
"""Crop the entire image to the selected area."""
|
||||
if self._currentImage 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
|
||||
|
||||
# Validate coordinates
|
||||
if right <= left or bottom <= top:
|
||||
return
|
||||
|
||||
# Get the original image
|
||||
original_image = self._currentImage.getImage()
|
||||
if original_image is None:
|
||||
return
|
||||
|
||||
img_width, img_height = original_image.size
|
||||
|
||||
# Ensure coordinates are within image bounds
|
||||
left = max(0, min(left, img_width))
|
||||
top = max(0, min(top, img_height))
|
||||
right = max(left, min(right, img_width))
|
||||
bottom = max(top, min(bottom, img_height))
|
||||
|
||||
# Validate final coordinates
|
||||
if right <= left or bottom <= top:
|
||||
return
|
||||
|
||||
try:
|
||||
# Take undo snapshot
|
||||
self._currentImage.snapshot()
|
||||
|
||||
# Crop the image to the selection area
|
||||
cropped_image = original_image.crop((left, top, right, bottom))
|
||||
|
||||
# Update the current image
|
||||
self._currentImage._imageData = cropped_image
|
||||
|
||||
# Clear selection before re-rendering
|
||||
self._clearSelection()
|
||||
|
||||
# Re-render the image (without selection)
|
||||
self._renderCurrentImage()
|
||||
except Exception as e:
|
||||
# Silently handle errors - crop operation failed
|
||||
pass
|
||||
|
||||
def _applyManipulationToSelection(self, manipulation) -> None:
|
||||
"""Apply the specified manipulation to the selected area only."""
|
||||
if self._currentImage is None or not self._selectionArea.is_active:
|
||||
@@ -531,11 +604,19 @@ class GUI:
|
||||
# Convert image coordinates to canvas coordinates
|
||||
pil_image = self._currentImage.getImage()
|
||||
img_width, img_height = pil_image.size
|
||||
canvas_width = self._imageCanvas.winfo_width()
|
||||
canvas_height = self._imageCanvas.winfo_height()
|
||||
|
||||
if canvas_width <= 0 or canvas_height <= 0:
|
||||
return
|
||||
# Get canvas dimensions for scaling
|
||||
# Use stored canvas image dimensions if available (from when image was rendered)
|
||||
if self._canvasImageWidth and self._canvasImageHeight:
|
||||
canvas_width = self._canvasImageWidth
|
||||
canvas_height = self._canvasImageHeight
|
||||
else:
|
||||
# Fallback: use actual canvas widget dimensions
|
||||
canvas_width = self._imageCanvas.winfo_width()
|
||||
canvas_height = self._imageCanvas.winfo_height()
|
||||
|
||||
if canvas_width <= 0 or canvas_height <= 0:
|
||||
return
|
||||
|
||||
# Calculate scaling factors
|
||||
scale_x = canvas_width / img_width
|
||||
|
||||
Reference in New Issue
Block a user