diff --git a/croppa/main.py b/croppa/main.py index bff5059..06d7d63 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -1241,10 +1241,17 @@ class VideoEditor: # Apply brightness/contrast first (to original frame for best quality) processed_frame = self.apply_brightness_contrast(processed_frame) - # Apply crop + # Apply crop with motion tracking if self.crop_rect: x, y, w, h = self.crop_rect x, y, w, h = int(x), int(y), int(w), int(h) + + # Apply motion tracking offset to move crop center to tracked point + if self.motion_tracker.tracking_enabled: + tracking_offset_x, tracking_offset_y = self.motion_tracker.get_tracking_offset(self.current_frame) + x += int(tracking_offset_x) + y += int(tracking_offset_y) + # Ensure crop is within frame bounds x = max(0, min(x, processed_frame.shape[1] - 1)) y = max(0, min(y, processed_frame.shape[0] - 1)) @@ -1266,14 +1273,11 @@ class VideoEditor: processed_frame, (new_width, new_height), interpolation=cv2.INTER_LINEAR ) - # Handle zoom center and display offset with motion tracking + # Handle zoom center and display offset if new_width > self.window_width or new_height > self.window_height: - # Apply motion tracking offset to display offset - tracking_offset_x, tracking_offset_y = self.motion_tracker.get_tracking_offset(self.current_frame) - # Calculate crop from zoomed image to fit window - start_x = max(0, self.display_offset[0] + int(tracking_offset_x)) - start_y = max(0, self.display_offset[1] + int(tracking_offset_y)) + start_x = max(0, self.display_offset[0]) + start_y = max(0, self.display_offset[1]) end_x = min(new_width, start_x + self.window_width) end_y = min(new_height, start_y + self.window_height) processed_frame = processed_frame[start_y:end_y, start_x:end_x] @@ -2224,6 +2228,13 @@ class VideoEditor: # Add the crop offset to get back to original frame coordinates if self.crop_rect: crop_x, crop_y, crop_w, crop_h = self.crop_rect + + # Account for motion tracking offset that was applied to the crop + if self.motion_tracker.tracking_enabled: + tracking_offset_x, tracking_offset_y = self.motion_tracker.get_tracking_offset(self.current_frame) + crop_x -= int(tracking_offset_x) + crop_y -= int(tracking_offset_y) + original_x += crop_x original_y += crop_y @@ -3232,14 +3243,14 @@ class VideoEditor: print("No render operation to cancel") # Individual direction controls using shift combinations we can detect - elif key == ord("J"): # Shift+j - expand up (relative to rotation) + elif key == ord("J"): # Shift+j - expand down (relative to rotation) direction = self.get_rotated_direction('j') self.adjust_crop_size(direction, False) - print(f"Expanded crop upward by {self.crop_size_step}px") - elif key == ord("K"): # Shift+k - expand down (relative to rotation) + print(f"Expanded crop downward by {self.crop_size_step}px") + elif key == ord("K"): # Shift+k - expand up (relative to rotation) direction = self.get_rotated_direction('k') self.adjust_crop_size(direction, False) - print(f"Expanded crop downward by {self.crop_size_step}px") + print(f"Expanded crop upward by {self.crop_size_step}px") elif key == ord("L"): # Shift+l - expand right (relative to rotation) direction = self.get_rotated_direction('l') self.adjust_crop_size(direction, False)