fixing cropping coordinates

This commit is contained in:
vb
2025-11-05 18:37:32 +01:00
parent f34bf706fb
commit 63529b1e3c

View File

@@ -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