diff --git a/photo_tagger.py b/photo_tagger.py index 2f3451d..796250b 100644 --- a/photo_tagger.py +++ b/photo_tagger.py @@ -1141,10 +1141,14 @@ class PhotoTagger: # Image display (left panel) image_frame = ttk.Frame(left_panel) image_frame.grid(row=0, column=0, pady=(0, 10), sticky=(tk.W, tk.E, tk.N, tk.S)) + image_frame.columnconfigure(0, weight=1) + image_frame.rowconfigure(0, weight=1) # Create canvas for image display - canvas = tk.Canvas(image_frame, width=400, height=400, bg='white') - canvas.grid(row=0, column=0) + style = ttk.Style() + canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9' + canvas = tk.Canvas(image_frame, width=400, height=400, bg=canvas_bg_color, highlightthickness=0) + canvas.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S)) # Input section (left panel) input_frame = ttk.LabelFrame(left_panel, text="Person Identification", padding="10") @@ -1718,7 +1722,9 @@ class PhotoTagger: clear_all_btn.config(state='disabled') # Create canvas for similar faces with scrollbar - similar_canvas = tk.Canvas(similar_faces_frame, bg='white') + style = ttk.Style() + canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9' + similar_canvas = tk.Canvas(similar_faces_frame, bg=canvas_bg_color, highlightthickness=0) similar_scrollbar = ttk.Scrollbar(similar_faces_frame, orient="vertical", command=similar_canvas.yview) similar_scrollable_frame = ttk.Frame(similar_canvas) @@ -2171,12 +2177,43 @@ class PhotoTagger: try: # Load and display the face crop image pil_image = Image.open(face_crop_path) - # Resize image to fit in window (max 400x400) - pil_image.thumbnail((400, 400), Image.Resampling.LANCZOS) + + # Get canvas dimensions + canvas_width = canvas.winfo_width() + canvas_height = canvas.winfo_height() + + # If canvas hasn't been rendered yet, force update and use actual size + if canvas_width <= 1 or canvas_height <= 1: + # Force the canvas to update its geometry + canvas.update_idletasks() + canvas_width = canvas.winfo_width() + canvas_height = canvas.winfo_height() + + # If still not rendered, use default size + if canvas_width <= 1: + canvas_width = 400 + if canvas_height <= 1: + canvas_height = 400 + + # Calculate scaling to fit within the canvas while maintaining aspect ratio + img_width, img_height = pil_image.size + scale_x = canvas_width / img_width + scale_y = canvas_height / img_height + # Allow slight upscaling (up to 1.2x) for better visibility, but cap to avoid excessive blurriness + max_scale = min(1.2, max(scale_x, scale_y)) + scale = min(scale_x, scale_y, max_scale) + + # Resize image to fill canvas + new_width = int(img_width * scale) + new_height = int(img_height * scale) + pil_image = pil_image.resize((new_width, new_height), Image.Resampling.LANCZOS) + photo = ImageTk.PhotoImage(pil_image) - # Update canvas - canvas.create_image(200, 200, image=photo) + # Center the image in the canvas + x = canvas_width // 2 + y = canvas_height // 2 + canvas.create_image(x, y, image=photo) # Keep a reference to prevent garbage collection canvas.image = photo @@ -2592,20 +2629,21 @@ class PhotoTagger: # Bind the callback to the variable match_var.trace('w', make_callback(match_var, current_face_id, similar_face_id)) - # Create a frame for the checkbox and text labels - text_frame = ttk.Frame(match_frame) - text_frame.pack(side=tk.LEFT, padx=(0, 10)) + # Configure match frame for grid layout + match_frame.columnconfigure(0, weight=0) # Checkbox column - fixed width + match_frame.columnconfigure(1, weight=1) # Text column - expandable + match_frame.columnconfigure(2, weight=0) # Image column - fixed width # Checkbox without text - checkbox = ttk.Checkbutton(text_frame, variable=match_var) - checkbox.pack(side=tk.LEFT, padx=(0, 5)) + checkbox = ttk.Checkbutton(match_frame, variable=match_var) + checkbox.grid(row=0, column=0, rowspan=2, sticky=(tk.W, tk.N), padx=(0, 5)) # Create labels for confidence and filename - confidence_label = ttk.Label(text_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold")) - confidence_label.pack(anchor=tk.W) + confidence_label = ttk.Label(match_frame, text=f"{confidence_pct:.1f}% {confidence_desc}", font=("Arial", 9, "bold")) + confidence_label.grid(row=0, column=1, sticky=tk.W, padx=(0, 10)) - filename_label = ttk.Label(text_frame, text=f"📁 {filename}", font=("Arial", 8), foreground="gray") - filename_label.pack(anchor=tk.W) + filename_label = ttk.Label(match_frame, text=f"📁 {filename}", font=("Arial", 8), foreground="gray") + filename_label.grid(row=1, column=1, sticky=tk.W, padx=(0, 10)) # Face image (reusing auto-match image display) try: @@ -2632,8 +2670,10 @@ class PhotoTagger: face_crops.append(face_crop_path) # Create canvas for face image (like in auto-match) - match_canvas = tk.Canvas(match_frame, width=80, height=80, bg='white') - match_canvas.pack(side=tk.LEFT, padx=(10, 0)) + style = ttk.Style() + canvas_bg_color = style.lookup('TFrame', 'background') or '#d9d9d9' + match_canvas = tk.Canvas(match_frame, width=80, height=80, bg=canvas_bg_color, highlightthickness=0) + match_canvas.grid(row=0, column=2, rowspan=2, sticky=(tk.W, tk.N), padx=(10, 0)) # Load and display image (reusing auto-match image loading) pil_image = Image.open(face_crop_path)