From c7c9012ef1a358f0e621c307231b67f7490c75b6 Mon Sep 17 00:00:00 2001 From: PhatPhuckDave Date: Tue, 23 Dec 2025 14:01:50 +0100 Subject: [PATCH] Fix realtime resizing --- croppa/main.py | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/croppa/main.py b/croppa/main.py index 6b65f31..7711a41 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -156,7 +156,6 @@ class VideoEditor: self.crop_border_dragging = False self.crop_border_drag_start_pos = None # (screen_x, screen_y) when drag started self.crop_border_drag_start_rect = None # (x, y, w, h) in rotated coords when drag started - self.crop_drag_edge = None # 'left', 'right', 'top', 'bottom' self.crop_drag_mode = None # 'expand' or 'contract' self.mouse_left_down = False self.mouse_right_down = False @@ -750,14 +749,6 @@ class VideoEditor: frames = direction * int(base_frames * self.seek_multiplier) self.seek_video(frames) - def seek_video_exact_frame(self, direction: int): - """Seek video by exactly 1 frame, unaffected by seek multiplier""" - if self.is_image_mode: - return - - frames = direction # Always exactly 1 frame - self.seek_video(frames) - def start_auto_repeat_seek(self, direction: int, shift_pressed: bool, ctrl_pressed: bool): """Start auto-repeat seeking""" if self.is_image_mode: @@ -1306,6 +1297,14 @@ class VideoEditor: def get_interpolated_crop_zoom(self, frame_index): """Return (crop_rect, zoom_factor) for the given frame, using keyframe interpolation when available.""" + # For the current frame, use live crop/zoom only when actively dragging (for real-time feedback) + # Otherwise, use interpolation even for current frame so playback shows smooth transitions + use_live_values = (frame_index == getattr(self, 'current_frame', 0) and + getattr(self, 'crop_border_dragging', False)) + if use_live_values: + base_rect = self._get_base_crop_rect_for_frame(frame_index) + return base_rect, self.zoom_factor + if not self.crop_zoom_keyframes: base_rect = self._get_base_crop_rect_for_frame(frame_index) return base_rect, self.zoom_factor @@ -1373,12 +1372,8 @@ class VideoEditor: return frame_index = getattr(self, 'current_frame', 0) frames = sorted(self.crop_zoom_keyframes.keys()) - prev_frame = None - for f in frames: - if f <= frame_index: - prev_frame = f - if f > frame_index: - break + prev_candidates = [f for f in frames if f < frame_index] + prev_frame = max(prev_candidates) if prev_candidates else None if prev_frame is None: self.show_feedback_message("No previous crop/zoom keyframe to clone") return @@ -2858,12 +2853,12 @@ class VideoEditor: # Draw template start point start_progress = start_frame / max(1, self.total_frames - 1) start_x = bar_x_start + int(bar_width * start_progress) - + # Template color (green for active, red for inactive) template_index = self.get_template_for_frame(self.current_frame) is_active = (template_index is not None and self.templates[template_index][0] == start_frame) template_color = (0, 255, 0) if is_active else (255, 0, 0) # Green if active, red if inactive - + # Draw template start marker cv2.rectangle( frame, @@ -2872,8 +2867,8 @@ class VideoEditor: template_color, -1, ) - - # Draw template number + + # Label template with its start frame cv2.putText( frame, str(start_frame), @@ -2884,6 +2879,20 @@ class VideoEditor: 1, ) + # Draw crop/zoom keyframe markers on timeline + if self.crop_zoom_keyframes: + for kf_frame in sorted(self.crop_zoom_keyframes.keys()): + kf_progress = kf_frame / max(1, self.total_frames - 1) + kf_x = bar_x_start + int(bar_width * kf_progress) + color = (0, 255, 255) if kf_frame == self.current_frame else (0, 200, 200) + cv2.line( + frame, + (kf_x, bar_y), + (kf_x, bar_y + self.TIMELINE_BAR_HEIGHT), + color, + 2 if kf_frame == self.current_frame else 1, + ) + # Draw frame difference threshold info region_status = "region" if self.interesting_region else "full frame" threshold_text = f"Interesting: {self.frame_difference_threshold:.0f}% (gap: {self.frame_difference_gap}, {region_status})" @@ -3239,7 +3248,6 @@ class VideoEditor: # First, compute the background rectangle bounds for both columns to cover all lines max_lines_in_col = max(len(col[1]) for col in columns) col_width = 890 # Leave some padding, adjust if needed - col_height = max_lines_in_col * line_height + 20 bg_rect_margin = 12 # Draw black background rectangles for both columns @@ -3563,7 +3571,6 @@ class VideoEditor: self.crop_border_dragging = False self.crop_border_drag_start_pos = None self.crop_border_drag_start_rect = None - self.crop_drag_edge = None self.crop_drag_mode = None self._update_crop_zoom_keyframe_for_current_frame() self.save_state()