diff --git a/src/poseguide/preview.py b/src/poseguide/preview.py new file mode 100644 index 0000000..8d006e5 --- /dev/null +++ b/src/poseguide/preview.py @@ -0,0 +1,27 @@ +import math + +def calculate_pose_placement(background_width: int, background_height: int, horizon_y: int, pose_joints: dict, margin: int = 20) -> dict: + """ + Calculates silhouette / stick figure placement bounding box respecting horizon and safe margins. + """ + if background_width <= 0 or background_height <= 0: + raise ValueError("Invalid background dimensions.") + if horizon_y < 0 or horizon_y > background_height: + raise ValueError("Horizon Y out of bounds.") + + scale_factor = (background_height - horizon_y) / float(background_height) + bbox_width = int((background_width * 0.3) * max(scale_factor, 0.4)) + bbox_height = int((background_height * 0.6) * max(scale_factor, 0.4)) + + # Center horizontally with safe margin constraint + center_x = background_width // 2 + min_x = max(margin, center_x - bbox_width // 2) + max_x = min(background_width - margin, center_x + bbox_width // 2) + min_y = max(margin, horizon_y) + max_y = min(background_height - margin, horizon_y + bbox_height) + + return { + "placement_box": {"x_min": min_x, "x_max": max_x, "y_min": min_y, "y_max": max_y}, + "scale": scale_factor, + "fits_safe_margin": (min_x >= margin and max_x <= background_width - margin and max_y <= background_height - margin) + } diff --git a/tests/test_pose_preview.py b/tests/test_pose_preview.py new file mode 100644 index 0000000..d50973e --- /dev/null +++ b/tests/test_pose_preview.py @@ -0,0 +1,22 @@ +import pytest +import sys +import os + +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) +from src.poseguide.preview import calculate_pose_placement + +def test_pose_placement_valid(): + """Test pose placement box respects horizon and safe margins.""" + bg_w, bg_h = 1920, 1080 + horizon = 540 + joints = {"head": [0.5, 0.2], "ankle": [0.5, 0.8]} + + result = calculate_pose_placement(bg_w, bg_h, horizon, joints, margin=20) + assert result["fits_safe_margin"] is True + assert result["placement_box"]["y_min"] >= horizon + assert result["placement_box"]["x_min"] >= 20 + +def test_pose_placement_invalid_dimensions(): + """Test pose placement raises ValueError on invalid background bounds.""" + with pytest.raises(ValueError, match="Invalid background dimensions"): + calculate_pose_placement(-100, 1080, 540, {})