Adding improvements to the grading
This commit is contained in:
@@ -26,6 +26,15 @@ class CutoutDefinition:
|
|||||||
height_percent: float = 0.0 # percentage (0.0-1.0) if height is -1
|
height_percent: float = 0.0 # percentage (0.0-1.0) if height is -1
|
||||||
width_percent: float = 0.0 # percentage (0.0-1.0) if width is -1
|
width_percent: float = 0.0 # percentage (0.0-1.0) if width is -1
|
||||||
|
|
||||||
|
# New center-based model (opt-in via cx/cy in project.json). When cx_percent is
|
||||||
|
# set: cx/cy are the CENTER as fractions of frame width/height; width_percent and
|
||||||
|
# height_percent are fractions of min(W,H) (so equal values → a true square on any
|
||||||
|
# aspect ratio); margin_percent is a per-side inset, also a fraction of min(W,H).
|
||||||
|
cx_percent: Optional[float] = None
|
||||||
|
cy_percent: Optional[float] = None
|
||||||
|
margin_percent: float = 0.0
|
||||||
|
size_relative_to_min: bool = False
|
||||||
|
|
||||||
|
|
||||||
# Backwards compatibility alias
|
# Backwards compatibility alias
|
||||||
TalkingHeadConfig = CutoutDefinition
|
TalkingHeadConfig = CutoutDefinition
|
||||||
|
|||||||
@@ -223,6 +223,24 @@ def parse_project_config(project_path: Path) -> ProjectConfig:
|
|||||||
# override the built-ins above.
|
# override the built-ins above.
|
||||||
cutouts_data = data.get("cutouts", {})
|
cutouts_data = data.get("cutouts", {})
|
||||||
for cutout_name, cutout_data in cutouts_data.items():
|
for cutout_name, cutout_data in cutouts_data.items():
|
||||||
|
if "cx" in cutout_data or "cy" in cutout_data:
|
||||||
|
# New center-based model: cx/cy are the center (fractions of frame W/H);
|
||||||
|
# width/height/margin are fractions of min(W,H). width==height → square.
|
||||||
|
w_pct = _parse_percent(cutout_data.get("width", "100%"))
|
||||||
|
h_pct = _parse_percent(cutout_data.get("height", cutout_data.get("width", "100%")))
|
||||||
|
cutouts[cutout_name] = CutoutDefinition(
|
||||||
|
x=-1,
|
||||||
|
y=-1,
|
||||||
|
height=-1,
|
||||||
|
width=-1,
|
||||||
|
cx_percent=_parse_percent(cutout_data.get("cx", "50%")),
|
||||||
|
cy_percent=_parse_percent(cutout_data.get("cy", "50%")),
|
||||||
|
width_percent=w_pct,
|
||||||
|
height_percent=h_pct,
|
||||||
|
margin_percent=_parse_percent(cutout_data.get("margin", "0%")),
|
||||||
|
size_relative_to_min=True,
|
||||||
|
)
|
||||||
|
continue
|
||||||
x, x_pct = _parse_dimension(cutout_data.get("x", 0))
|
x, x_pct = _parse_dimension(cutout_data.get("x", 0))
|
||||||
y, y_pct = _parse_dimension(cutout_data.get("y", 0))
|
y, y_pct = _parse_dimension(cutout_data.get("y", 0))
|
||||||
height, height_pct = _parse_dimension(cutout_data.get("height", 200))
|
height, height_pct = _parse_dimension(cutout_data.get("height", 200))
|
||||||
@@ -290,6 +308,20 @@ def _parse_dimension(value: Any) -> tuple[int, float]:
|
|||||||
return 200, 0.0 # default
|
return 200, 0.0 # default
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_percent(value: Any, default: float = 0.0) -> float:
|
||||||
|
"""Parse a percentage into a 0.0-based fraction. '177%' → 1.77; a bare number
|
||||||
|
is taken as an already-computed fraction (1.77 → 1.77). Used by the center-based
|
||||||
|
cutout model where values can exceed 100% (fullscreen width on 16:9)."""
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
if isinstance(value, str):
|
||||||
|
v = value.strip()
|
||||||
|
if v.endswith("%"):
|
||||||
|
return float(v[:-1]) / 100.0
|
||||||
|
return float(v)
|
||||||
|
return float(value)
|
||||||
|
|
||||||
|
|
||||||
def parse_slides(
|
def parse_slides(
|
||||||
project_path: Path, config: ProjectConfig = None
|
project_path: Path, config: ProjectConfig = None
|
||||||
) -> dict[str, SlideDefinition]:
|
) -> dict[str, SlideDefinition]:
|
||||||
|
|||||||
+17
-1
@@ -675,8 +675,24 @@ def _calculate_cutout_position(
|
|||||||
) -> tuple[int, int, int, int]:
|
) -> tuple[int, int, int, int]:
|
||||||
"""Calculate pixel position, width, and height from cutout definition.
|
"""Calculate pixel position, width, and height from cutout definition.
|
||||||
|
|
||||||
Returns: (x, y, width, height)
|
Returns: (x, y, width, height) — top-left corner + size, in pixels.
|
||||||
"""
|
"""
|
||||||
|
# New center-based model: cx/cy are the center as fractions of frame W/H;
|
||||||
|
# width/height/margin are fractions of min(W,H) so a square stays square on any
|
||||||
|
# aspect ratio. margin insets each side.
|
||||||
|
if cutout.cx_percent is not None:
|
||||||
|
m = min(frame_width, frame_height)
|
||||||
|
margin_px = cutout.margin_percent * m
|
||||||
|
cut_width = int(round(cutout.width_percent * m - 2 * margin_px))
|
||||||
|
cut_height = int(round(cutout.height_percent * m - 2 * margin_px))
|
||||||
|
cut_width = max(0, cut_width)
|
||||||
|
cut_height = max(0, cut_height)
|
||||||
|
center_x = cutout.cx_percent * frame_width
|
||||||
|
center_y = cutout.cy_percent * frame_height
|
||||||
|
cut_x = int(round(center_x - cut_width / 2))
|
||||||
|
cut_y = int(round(center_y - cut_height / 2))
|
||||||
|
return cut_x, cut_y, cut_width, cut_height
|
||||||
|
|
||||||
# Calculate height
|
# Calculate height
|
||||||
if cutout.height >= 0:
|
if cutout.height >= 0:
|
||||||
cut_height = cutout.height
|
cut_height = cutout.height
|
||||||
|
|||||||
Reference in New Issue
Block a user