Add S-expression based video effects pipeline with modular effect definitions, constructs, and recipe files. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
87 lines
2.2 KiB
Python
87 lines
2.2 KiB
Python
# /// script
|
|
# requires-python = ">=3.10"
|
|
# dependencies = ["numpy"]
|
|
# ///
|
|
"""
|
|
@effect mirror
|
|
@version 1.0.0
|
|
@author artdag
|
|
|
|
@description
|
|
Creates mirror/reflection effects by duplicating and flipping portions
|
|
of the frame. Can create kaleidoscope-like symmetry effects.
|
|
|
|
@param mode string
|
|
@enum left right top bottom quad
|
|
@default left
|
|
Mirror mode:
|
|
- left: Left half mirrored to right
|
|
- right: Right half mirrored to left
|
|
- top: Top half mirrored to bottom
|
|
- bottom: Bottom half mirrored to top
|
|
- quad: Four-way symmetry (kaleidoscope)
|
|
|
|
@example
|
|
(effect mirror :mode "left")
|
|
|
|
@example
|
|
(effect mirror :mode "quad") ; kaleidoscope effect
|
|
"""
|
|
|
|
import numpy as np
|
|
|
|
|
|
def process_frame(frame: np.ndarray, params: dict, state: dict) -> tuple:
|
|
"""
|
|
Create mirror/reflection effects.
|
|
|
|
Args:
|
|
frame: Input frame as numpy array (H, W, 3) RGB uint8
|
|
params: Effect parameters
|
|
- mode: mirror mode (default "left")
|
|
state: Persistent state dict (unused)
|
|
|
|
Returns:
|
|
Tuple of (processed_frame, new_state)
|
|
"""
|
|
mode = params.get("mode", "left")
|
|
|
|
h, w = frame.shape[:2]
|
|
result = frame.copy()
|
|
|
|
if mode == "left":
|
|
# Mirror left half to right
|
|
half = w // 2
|
|
result[:, half:] = np.flip(result[:, :half], axis=1)[:, :w - half]
|
|
|
|
elif mode == "right":
|
|
# Mirror right half to left
|
|
half = w // 2
|
|
result[:, :half] = np.flip(result[:, half:], axis=1)[:, :half]
|
|
|
|
elif mode == "top":
|
|
# Mirror top half to bottom
|
|
half = h // 2
|
|
result[half:, :] = np.flip(result[:half, :], axis=0)[:h - half, :]
|
|
|
|
elif mode == "bottom":
|
|
# Mirror bottom half to top
|
|
half = h // 2
|
|
result[:half, :] = np.flip(result[half:, :], axis=0)[:half, :]
|
|
|
|
elif mode == "quad":
|
|
# Four-way symmetry: use top-left quadrant
|
|
half_h = h // 2
|
|
half_w = w // 2
|
|
|
|
# Get top-left quadrant
|
|
tl = result[:half_h, :half_w]
|
|
|
|
# Mirror to top-right
|
|
result[:half_h, half_w:] = np.flip(tl, axis=1)[:, :w - half_w]
|
|
|
|
# Mirror top half to bottom
|
|
result[half_h:, :] = np.flip(result[:half_h, :], axis=0)[:h - half_h, :]
|
|
|
|
return np.ascontiguousarray(result), state
|