diff --git a/croppa/main.py b/croppa/main.py index 24dedfb..ffa613d 100644 --- a/croppa/main.py +++ b/croppa/main.py @@ -125,6 +125,11 @@ class VideoEditor: self.progress_bar_text = "" self.progress_bar_fps = 0.0 # Current rendering FPS + # Feedback message state + self.feedback_message = "" + self.feedback_message_time = None + self.feedback_message_duration = 0.7 # seconds to show message + # Crop adjustment settings self.crop_size_step = self.CROP_SIZE_STEP @@ -208,12 +213,15 @@ class VideoEditor: success = cv2.imwrite(str(screenshot_path), processed_frame) if success: print(f"Screenshot saved: {screenshot_name}") + self.show_feedback_message(f"Screenshot saved: {screenshot_name}") return True else: print(f"Error: Could not save screenshot to {screenshot_path}") + self.show_feedback_message("Error: Could not save screenshot") return False else: print("Error: Could not process frame for screenshot") + self.show_feedback_message("Error: Could not process frame") return False def _get_media_files_from_directory(self, directory: Path) -> List[Path]: @@ -578,6 +586,52 @@ class VideoEditor: self.progress_bar_complete_time = None self.progress_bar_fps = 0.0 + def show_feedback_message(self, message: str): + """Show a feedback message on screen for a few seconds""" + self.feedback_message = message + self.feedback_message_time = time.time() + + def draw_feedback_message(self, frame): + """Draw feedback message on frame if visible""" + if not self.feedback_message or not self.feedback_message_time: + return + + # Check if message should still be shown + elapsed = time.time() - self.feedback_message_time + if elapsed > self.feedback_message_duration: + self.feedback_message = "" + self.feedback_message_time = None + return + + height, width = frame.shape[:2] + + # Calculate message position (center of frame) + font = cv2.FONT_HERSHEY_SIMPLEX + font_scale = 1.0 + thickness = 2 + + # Get text size + text_size = cv2.getTextSize(self.feedback_message, font, font_scale, thickness)[0] + text_x = (width - text_size[0]) // 2 + text_y = (height + text_size[1]) // 2 + + # Draw background rectangle + padding = 10 + rect_x1 = text_x - padding + rect_y1 = text_y - text_size[1] - padding + rect_x2 = text_x + text_size[0] + padding + rect_y2 = text_y + padding + + # Semi-transparent background + overlay = frame.copy() + cv2.rectangle(overlay, (rect_x1, rect_y1), (rect_x2, rect_y2), (0, 0, 0), -1) + alpha = 0.7 + cv2.addWeighted(overlay, alpha, frame, 1 - alpha, 0, frame) + + # Draw text with shadow + cv2.putText(frame, self.feedback_message, (text_x + 2, text_y + 2), font, font_scale, (0, 0, 0), thickness + 1) + cv2.putText(frame, self.feedback_message, (text_x, text_y), font, font_scale, (255, 255, 255), thickness) + def draw_progress_bar(self, frame): """Draw progress bar on frame if visible - positioned at top with full width""" if not self.progress_bar_visible: @@ -980,6 +1034,9 @@ class VideoEditor: # Draw progress bar (if visible) self.draw_progress_bar(canvas) + # Draw feedback message (if visible) + self.draw_feedback_message(canvas) + window_title = "Image Editor" if self.is_image_mode else "Video Editor" cv2.imshow(window_title, canvas)