Module effects

Source
Expand description

Per-clip effects (CPU, RGBA8). apply runs on the decoded layer image (at its decode size, straight alpha) in stack order, before placement/blending. Pixel-sized parameters (blur radius, pixel block, wobble amplitude) are project pixels; scale = canvas px per project px converts them. Wobble is geometric: it does not touch pixels — the compositor adds wobble() to the placement.

Implementations (all O(pixels), no per-call allocation beyond scratch):

  • Blur: 3 passes of a separable box blur ≈ Gaussian (radius*scale px).
  • Pixelate: average over blocks of (size*scale) px.
  • Tint: mix each pixel towards (r,g,b) by amount.
  • Color: brightness (add), contrast (around 0.5), saturation (mix with luma), hue (rotate in YIQ), gamma (LUT); build one 256-entry LUT per channel where possible.
  • Vignette: darken by strength outside radius (normalised to half the diagonal) with softness.
  • Sharpen: unsharp mask (img + amount * (img - blur(radius))).
  • Invert / Grayscale: mix by amount.
  • Flip: horizontal / vertical mirror (params >= 0.5 = on).
  • Crop: fractions cut from each edge (alpha = 0), with an optional feathered edge.
  • Threshold / Levels / Curves: one 256-entry LUT per channel.
  • HueShift: RGB -> HSL -> RGB per pixel.
  • ChromaKey: Cb/Cr distance to the key colour with spill removal (no edge shrink — that needs neighbourhood taps; the GPU body does it).
  • RecDot: a blinking dot plus a seven-segment HH:MM:SS timecode drawn as rectangles.

Still GPU-only (engine/shaders.rs has the fragment bodies, the CPU path leaves the layer alone): Vhs, MotionBlur, EdgeGlow, JpegCompress, the BlobTrack overlay and user Shaders. track below is the CPU half of BlobTrack — it runs anywhere, so the tracked centroid can drive properties even without a GL context.

Constants§

SEGMENTS 🔒
SEG_T 🔒
Segment geometry in digit-cell units (cx, cy, half-w, half-h) with T the stroke thickness.
SEVEN_SEG 🔒
Seven-segment masks for 0..9 (bit 0 = top, then clockwise from top-right, bit 6 = middle).

Functions§

apply
Apply one effect in place at clip-local time t. scratch is a reusable buffer.
apply_lut 🔒
blur_dir 🔒
1-D sliding-window box blur of all 4 channels along rows (horiz) or columns, edge replicate.
blur_pass 🔒
One separable box pass (radius r, edge-replicated): rows img→scratch, columns scratch→img.
chroma_key 🔒
color 🔒
Brightness/contrast/gamma via one LUT; saturation + hue via one combined 3×3 matrix (Rec.709 luma).
color_replace 🔒
Key out colours near key (0..255) by their Cb/Cr distance, with spill removal. No edge shrink — that needs neighbourhood taps; shaders::CHROMA_KEY does it on the GPU. Blend every pixel within tol of from towards to, fading out over tol .. tol + soft. Distances are normalised so 1.0 is the full black-to-white diagonal, matching the GPU body.
crop 🔒
Cut l/r/t/b fractions from the edges (alpha 0 outside), feathering over feather * min(w,h) px.
curve_at
Monotone cubic (Fritsch–Carlson) through (0,0) (0.25,a) (0.5,b) (0.75,c) (1,1) — the exact curve shaders::CURVES evaluates on the GPU, so preview and export agree.
curves 🔒
Per-channel curves then the master curve (12 knots: master, R, G, B).
draw_digit 🔒
fill_rect 🔒
Opaque axis-aligned rectangle (canvas px, clipped).
flip 🔒
gpu_only
True for kinds that only exist as GPU shaders (engine/gpu): apply leaves the layer untouched, so previews and exports on a machine without a GL context degrade gracefully instead of panicking. Callers that must warn about what a CPU render drops (export) share this list.
hsl_to_rgb 🔒
hue_shift 🔒
Rotate hue by deg, scale saturation, offset lightness.
levels 🔒
Remap [in_black, in_white] onto [out_black, out_white] through gamma (v^(1/g), like Color).
lut_from 🔒
Build a 256-entry LUT from a 0..1 -> 0..1 function.
pixelate 🔒
Average each block of block×block px in place.
px 🔒
A pixel-sized parameter (project px) as whole image px at scale, floored at min. A non-zero request never rounds down to nothing, so a small radius still shows in the small preview canvas instead of appearing only on export (preview == export).
rec_dot 🔒
Blinking record dot in a corner (0 = TL, 1 = TR, 2 = BL, 3 = BR) plus an optional HH:MM:SS timecode.
rgb_to_hsl 🔒
Rec.601-free HSL round trip (matches the GPU body): hue in turns, s/l in 0..1.
sharpen 🔒
Unsharp mask: img + amount * (img - box_blur(img, r)). One separable box pass; the vertical pass reads the h-blurred scratch and combines with the untouched original in place.
smoothstep 🔒
threshold 🔒
Posterise to black/white at level with a softness-wide ramp, on luma or per channel.
to_ycc 🔒
track
BlobTrack on the CPU: the centroid of every pixel within Tolerance of the target colour, as (cx, cy) in 0..1 layer coordinates plus the matched area as a fraction of the frame. None when nothing matches. params is the effect’s parameter list (EffectKind::BlobTrack.params() order).
vignette 🔒
Darken by strength outside radius (0..1.5 of the half diagonal) with a softness falloff.
wobble
Placement deltas for a geometric effect at clip-local time t: (dx, dy) in project px, (roll, yaw, pitch) in degrees.
wobble_wave 🔒
One shake axis in -1..1. method picks the waveform (see model::WOBBLE_MOTIONS), w is the phase in radians and p the per-axis offset so the axes never move together.