Adding improvements to the grading

This commit is contained in:
2026-07-24 17:36:02 +02:00
parent 5a439380ae
commit 35c5e52fb0
3 changed files with 58 additions and 1 deletions
+9
View File
@@ -26,6 +26,15 @@ class CutoutDefinition:
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
# 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
TalkingHeadConfig = CutoutDefinition
+32
View File
@@ -223,6 +223,24 @@ def parse_project_config(project_path: Path) -> ProjectConfig:
# override the built-ins above.
cutouts_data = data.get("cutouts", {})
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))
y, y_pct = _parse_dimension(cutout_data.get("y", 0))
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
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(
project_path: Path, config: ProjectConfig = None
) -> dict[str, SlideDefinition]:
+17 -1
View File
@@ -675,8 +675,24 @@ def _calculate_cutout_position(
) -> tuple[int, int, int, int]:
"""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
if cutout.height >= 0:
cut_height = cutout.height