Replace batch DAG system with streaming architecture
- Remove legacy_tasks.py, hybrid_state.py, render.py - Remove old task modules (analyze, execute, execute_sexp, orchestrate) - Add streaming interpreter from test repo - Add sexp_effects with primitives and video effects - Add streaming Celery task with CID-based asset resolution - Support both CID and friendly name references for assets - Add .dockerignore to prevent local clones from conflicting Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
17
sexp_effects/effects/ascii_art.sexp
Normal file
17
sexp_effects/effects/ascii_art.sexp
Normal file
@@ -0,0 +1,17 @@
|
||||
;; ASCII Art effect - converts image to ASCII characters
|
||||
(require-primitives "ascii")
|
||||
|
||||
(define-effect ascii_art
|
||||
:params (
|
||||
(char_size :type int :default 8 :range [4 32])
|
||||
(alphabet :type string :default "standard")
|
||||
(color_mode :type string :default "color" :desc ""color", "mono", "invert", or any color name/hex")
|
||||
(background_color :type string :default "black" :desc "background color name/hex")
|
||||
(invert_colors :type int :default 0 :desc "swap foreground and background colors")
|
||||
(contrast :type float :default 1.5 :range [1 3])
|
||||
)
|
||||
(let* ((sample (cell-sample frame char_size))
|
||||
(colors (nth sample 0))
|
||||
(luminances (nth sample 1))
|
||||
(chars (luminance-to-chars luminances alphabet contrast)))
|
||||
(render-char-grid frame chars colors char_size color_mode background_color invert_colors)))
|
||||
52
sexp_effects/effects/ascii_art_fx.sexp
Normal file
52
sexp_effects/effects/ascii_art_fx.sexp
Normal file
@@ -0,0 +1,52 @@
|
||||
;; ASCII Art FX - converts image to ASCII characters with per-character effects
|
||||
(require-primitives "ascii")
|
||||
|
||||
(define-effect ascii_art_fx
|
||||
:params (
|
||||
;; Basic parameters
|
||||
(char_size :type int :default 8 :range [4 32]
|
||||
:desc "Size of each character cell in pixels")
|
||||
(alphabet :type string :default "standard"
|
||||
:desc "Character set to use")
|
||||
(color_mode :type string :default "color"
|
||||
:choices [color mono invert]
|
||||
:desc "Color mode: color, mono, invert, or any color name/hex")
|
||||
(background_color :type string :default "black"
|
||||
:desc "Background color name or hex value")
|
||||
(invert_colors :type int :default 0 :range [0 1]
|
||||
:desc "Swap foreground and background colors (0/1)")
|
||||
(contrast :type float :default 1.5 :range [1 3]
|
||||
:desc "Character selection contrast")
|
||||
|
||||
;; Per-character effects
|
||||
(char_jitter :type float :default 0 :range [0 20]
|
||||
:desc "Position jitter amount in pixels")
|
||||
(char_scale :type float :default 1.0 :range [0.5 2.0]
|
||||
:desc "Character scale factor")
|
||||
(char_rotation :type float :default 0 :range [0 180]
|
||||
:desc "Rotation amount in degrees")
|
||||
(char_hue_shift :type float :default 0 :range [0 360]
|
||||
:desc "Hue shift in degrees")
|
||||
|
||||
;; Modulation sources
|
||||
(jitter_source :type string :default "none"
|
||||
:choices [none luminance inv_luminance saturation position_x position_y position_diag random center_dist]
|
||||
:desc "What drives jitter modulation")
|
||||
(scale_source :type string :default "none"
|
||||
:choices [none luminance inv_luminance saturation position_x position_y position_diag random center_dist]
|
||||
:desc "What drives scale modulation")
|
||||
(rotation_source :type string :default "none"
|
||||
:choices [none luminance inv_luminance saturation position_x position_y position_diag random center_dist]
|
||||
:desc "What drives rotation modulation")
|
||||
(hue_source :type string :default "none"
|
||||
:choices [none luminance inv_luminance saturation position_x position_y position_diag random center_dist]
|
||||
:desc "What drives hue shift modulation")
|
||||
)
|
||||
(let* ((sample (cell-sample frame char_size))
|
||||
(colors (nth sample 0))
|
||||
(luminances (nth sample 1))
|
||||
(chars (luminance-to-chars luminances alphabet contrast)))
|
||||
(render-char-grid-fx frame chars colors luminances char_size
|
||||
color_mode background_color invert_colors
|
||||
char_jitter char_scale char_rotation char_hue_shift
|
||||
jitter_source scale_source rotation_source hue_source)))
|
||||
102
sexp_effects/effects/ascii_fx_zone.sexp
Normal file
102
sexp_effects/effects/ascii_fx_zone.sexp
Normal file
@@ -0,0 +1,102 @@
|
||||
;; Composable ASCII Art with Per-Zone Expression-Driven Effects
|
||||
;; Requires ascii primitive library for the ascii-fx-zone primitive
|
||||
|
||||
(require-primitives "ascii")
|
||||
|
||||
;; Two modes of operation:
|
||||
;;
|
||||
;; 1. EXPRESSION MODE: Use zone-* variables in expression parameters
|
||||
;; Zone variables available:
|
||||
;; zone-row, zone-col: Grid position (integers)
|
||||
;; zone-row-norm, zone-col-norm: Normalized position (0-1)
|
||||
;; zone-lum: Cell luminance (0-1)
|
||||
;; zone-sat: Cell saturation (0-1)
|
||||
;; zone-hue: Cell hue (0-360)
|
||||
;; zone-r, zone-g, zone-b: RGB components (0-1)
|
||||
;;
|
||||
;; Example:
|
||||
;; (ascii-fx-zone frame
|
||||
;; :cols 80
|
||||
;; :char_hue (* zone-lum 180)
|
||||
;; :char_rotation (* zone-col-norm 30))
|
||||
;;
|
||||
;; 2. CELL EFFECT MODE: Pass a lambda to apply arbitrary effects per-cell
|
||||
;; The lambda receives (cell-image zone-dict) and returns modified cell.
|
||||
;; Zone dict contains: row, col, row-norm, col-norm, lum, sat, hue, r, g, b,
|
||||
;; char, color, cell_size, plus any bound analysis values.
|
||||
;;
|
||||
;; Any loaded sexp effect can be called on cells - each cell is just a small frame:
|
||||
;; (blur cell radius) - Gaussian blur
|
||||
;; (rotate cell angle) - Rotate by angle degrees
|
||||
;; (brightness cell factor) - Adjust brightness
|
||||
;; (contrast cell factor) - Adjust contrast
|
||||
;; (saturation cell factor) - Adjust saturation
|
||||
;; (hue_shift cell degrees) - Shift hue
|
||||
;; (rgb_split cell offset_x offset_y) - RGB channel split
|
||||
;; (invert cell) - Invert colors
|
||||
;; (pixelate cell block_size) - Pixelate
|
||||
;; (wave cell amplitude freq) - Wave distortion
|
||||
;; ... and any other loaded effect
|
||||
;;
|
||||
;; Example:
|
||||
;; (ascii-fx-zone frame
|
||||
;; :cols 60
|
||||
;; :cell_effect (lambda [cell zone]
|
||||
;; (blur (rotate cell (* (get zone "energy") 45))
|
||||
;; (if (> (get zone "lum") 0.5) 3 0))))
|
||||
|
||||
(define-effect ascii_fx_zone
|
||||
:params (
|
||||
(cols :type int :default 80 :range [20 200]
|
||||
:desc "Number of character columns")
|
||||
(char_size :type int :default nil :range [4 32]
|
||||
:desc "Character cell size in pixels (overrides cols if set)")
|
||||
(alphabet :type string :default "standard"
|
||||
:desc "Character set: standard, blocks, simple, digits, or custom string")
|
||||
(color_mode :type string :default "color"
|
||||
:desc "Color mode: color, mono, invert, or any color name/hex")
|
||||
(background :type string :default "black"
|
||||
:desc "Background color name or hex value")
|
||||
(contrast :type float :default 1.5 :range [0.5 3.0]
|
||||
:desc "Contrast for character selection")
|
||||
(char_hue :type any :default nil
|
||||
:desc "Hue shift expression (evaluated per-zone with zone-* vars)")
|
||||
(char_saturation :type any :default nil
|
||||
:desc "Saturation multiplier expression (1.0 = unchanged)")
|
||||
(char_brightness :type any :default nil
|
||||
:desc "Brightness multiplier expression (1.0 = unchanged)")
|
||||
(char_scale :type any :default nil
|
||||
:desc "Character scale expression (1.0 = normal size)")
|
||||
(char_rotation :type any :default nil
|
||||
:desc "Character rotation expression (degrees)")
|
||||
(char_jitter :type any :default nil
|
||||
:desc "Position jitter expression (pixels)")
|
||||
(cell_effect :type any :default nil
|
||||
:desc "Lambda (cell zone) -> cell for arbitrary per-cell effects")
|
||||
;; Convenience params for staged recipes (avoids compile-time expression issues)
|
||||
(energy :type float :default nil
|
||||
:desc "Energy multiplier (0-1) from audio analysis bind")
|
||||
(rotation_scale :type float :default 0
|
||||
:desc "Max rotation at top-right when energy=1 (degrees)")
|
||||
)
|
||||
;; The ascii-fx-zone special form handles expression params
|
||||
;; If energy + rotation_scale provided, it builds: energy * scale * position_factor
|
||||
;; where position_factor = 0 at bottom-left, 3 at top-right
|
||||
;; If cell_effect provided, each character is rendered to a cell image,
|
||||
;; passed to the lambda, and the result composited back
|
||||
(ascii-fx-zone frame
|
||||
:cols cols
|
||||
:char_size char_size
|
||||
:alphabet alphabet
|
||||
:color_mode color_mode
|
||||
:background background
|
||||
:contrast contrast
|
||||
:char_hue char_hue
|
||||
:char_saturation char_saturation
|
||||
:char_brightness char_brightness
|
||||
:char_scale char_scale
|
||||
:char_rotation char_rotation
|
||||
:char_jitter char_jitter
|
||||
:cell_effect cell_effect
|
||||
:energy energy
|
||||
:rotation_scale rotation_scale))
|
||||
30
sexp_effects/effects/ascii_zones.sexp
Normal file
30
sexp_effects/effects/ascii_zones.sexp
Normal file
@@ -0,0 +1,30 @@
|
||||
;; ASCII Zones effect - different character sets for different brightness zones
|
||||
;; Dark areas use simple chars, mid uses standard, bright uses blocks
|
||||
(require-primitives "ascii")
|
||||
|
||||
(define-effect ascii_zones
|
||||
:params (
|
||||
(char_size :type int :default 8 :range [4 32])
|
||||
(dark_threshold :type int :default 80 :range [0 128])
|
||||
(bright_threshold :type int :default 180 :range [128 255])
|
||||
(color_mode :type string :default "color")
|
||||
)
|
||||
(let* ((sample (cell-sample frame char_size))
|
||||
(colors (nth sample 0))
|
||||
(luminances (nth sample 1))
|
||||
;; Start with simple chars as base
|
||||
(base-chars (luminance-to-chars luminances "simple" 1.2))
|
||||
;; Map each cell to appropriate alphabet based on brightness zone
|
||||
(zoned-chars (map-char-grid base-chars luminances
|
||||
(lambda (r c ch lum)
|
||||
(cond
|
||||
;; Bright zones: use block characters
|
||||
((> lum bright_threshold)
|
||||
(alphabet-char "blocks" (floor (/ (- lum bright_threshold) 15))))
|
||||
;; Dark zones: use simple sparse chars
|
||||
((< lum dark_threshold)
|
||||
(alphabet-char " .-" (floor (/ lum 30))))
|
||||
;; Mid zones: use standard ASCII
|
||||
(else
|
||||
(alphabet-char "standard" (floor (/ lum 4)))))))))
|
||||
(render-char-grid frame zoned-chars colors char_size color_mode (list 0 0 0))))
|
||||
31
sexp_effects/effects/blend.sexp
Normal file
31
sexp_effects/effects/blend.sexp
Normal file
@@ -0,0 +1,31 @@
|
||||
;; Blend effect - combines two video frames
|
||||
;; Streaming-compatible: frame is background, overlay is second frame
|
||||
;; Usage: (blend background overlay :opacity 0.5 :mode "alpha")
|
||||
;;
|
||||
;; Params:
|
||||
;; mode - blend mode (add, multiply, screen, overlay, difference, lighten, darken, alpha)
|
||||
;; opacity - blend amount (0-1)
|
||||
|
||||
(require-primitives "image" "blending" "core")
|
||||
|
||||
(define-effect blend
|
||||
:params (
|
||||
(overlay :type frame :default nil)
|
||||
(mode :type string :default "alpha")
|
||||
(opacity :type float :default 0.5)
|
||||
)
|
||||
(if (core:is-nil overlay)
|
||||
frame
|
||||
(let [a frame
|
||||
b overlay
|
||||
a-h (image:height a)
|
||||
a-w (image:width a)
|
||||
b-h (image:height b)
|
||||
b-w (image:width b)
|
||||
;; Resize b to match a if needed
|
||||
b-sized (if (and (= a-w b-w) (= a-h b-h))
|
||||
b
|
||||
(image:resize b a-w a-h "linear"))]
|
||||
(if (= mode "alpha")
|
||||
(blending:blend-images a b-sized opacity)
|
||||
(blending:blend-images a (blending:blend-mode a b-sized mode) opacity)))))
|
||||
58
sexp_effects/effects/blend_multi.sexp
Normal file
58
sexp_effects/effects/blend_multi.sexp
Normal file
@@ -0,0 +1,58 @@
|
||||
;; N-way weighted blend effect
|
||||
;; Streaming-compatible: pass inputs as a list of frames
|
||||
;; Usage: (blend_multi :inputs [(read a) (read b) (read c)] :weights [0.3 0.4 0.3])
|
||||
;;
|
||||
;; Parameters:
|
||||
;; inputs - list of N frames to blend
|
||||
;; weights - list of N floats, one per input (resolved per-frame)
|
||||
;; mode - blend mode applied when folding each frame in:
|
||||
;; "alpha" — pure weighted average (default)
|
||||
;; "multiply" — darken by multiplication
|
||||
;; "screen" — lighten (inverse multiply)
|
||||
;; "overlay" — contrast-boosting midtone blend
|
||||
;; "soft-light" — gentle dodge/burn
|
||||
;; "hard-light" — strong dodge/burn
|
||||
;; "color-dodge" — brightens towards white
|
||||
;; "color-burn" — darkens towards black
|
||||
;; "difference" — absolute pixel difference
|
||||
;; "exclusion" — softer difference
|
||||
;; "add" — additive (clamped)
|
||||
;; "subtract" — subtractive (clamped)
|
||||
;; "darken" — per-pixel minimum
|
||||
;; "lighten" — per-pixel maximum
|
||||
;; resize_mode - how to match frame dimensions (fit, crop, stretch)
|
||||
;;
|
||||
;; Uses a left-fold over inputs[1..N-1]. At each step the running
|
||||
;; opacity is: w[i] / (w[0] + w[1] + ... + w[i])
|
||||
;; which produces the correct normalised weighted result.
|
||||
|
||||
(require-primitives "image" "blending")
|
||||
|
||||
(define-effect blend_multi
|
||||
:params (
|
||||
(inputs :type list :default [])
|
||||
(weights :type list :default [])
|
||||
(mode :type string :default "alpha")
|
||||
(resize_mode :type string :default "fit")
|
||||
)
|
||||
(let [n (len inputs)
|
||||
;; Target dimensions from first frame
|
||||
target-w (image:width (nth inputs 0))
|
||||
target-h (image:height (nth inputs 0))
|
||||
;; Fold over indices 1..n-1
|
||||
;; Accumulator is (list blended-frame running-weight-sum)
|
||||
seed (list (nth inputs 0) (nth weights 0))
|
||||
result (reduce (range 1 n) seed
|
||||
(lambda (pair i)
|
||||
(let [acc (nth pair 0)
|
||||
running (nth pair 1)
|
||||
w (nth weights i)
|
||||
new-running (+ running w)
|
||||
opacity (/ w (max new-running 0.001))
|
||||
f (image:resize (nth inputs i) target-w target-h "linear")
|
||||
;; Apply blend mode then mix with opacity
|
||||
blended (if (= mode "alpha")
|
||||
(blending:blend-images acc f opacity)
|
||||
(blending:blend-images acc (blending:blend-mode acc f mode) opacity))]
|
||||
(list blended new-running))))]
|
||||
(nth result 0)))
|
||||
16
sexp_effects/effects/bloom.sexp
Normal file
16
sexp_effects/effects/bloom.sexp
Normal file
@@ -0,0 +1,16 @@
|
||||
;; Bloom effect - glow on bright areas
|
||||
(require-primitives "image" "blending")
|
||||
|
||||
(define-effect bloom
|
||||
:params (
|
||||
(intensity :type float :default 0.5 :range [0 2])
|
||||
(threshold :type int :default 200 :range [0 255])
|
||||
(radius :type int :default 15 :range [1 50])
|
||||
)
|
||||
(let* ((bright (map-pixels frame
|
||||
(lambda (x y c)
|
||||
(if (> (luminance c) threshold)
|
||||
c
|
||||
(rgb 0 0 0)))))
|
||||
(blurred (image:blur bright radius)))
|
||||
(blending:blend-mode frame blurred "add")))
|
||||
8
sexp_effects/effects/blur.sexp
Normal file
8
sexp_effects/effects/blur.sexp
Normal file
@@ -0,0 +1,8 @@
|
||||
;; Blur effect - gaussian blur
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect blur
|
||||
:params (
|
||||
(radius :type int :default 5 :range [1 50])
|
||||
)
|
||||
(image:blur frame (max 1 radius)))
|
||||
9
sexp_effects/effects/brightness.sexp
Normal file
9
sexp_effects/effects/brightness.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Brightness effect - adjusts overall brightness
|
||||
;; Uses vectorized adjust primitive for fast processing
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect brightness
|
||||
:params (
|
||||
(amount :type int :default 0 :range [-255 255])
|
||||
)
|
||||
(color_ops:adjust-brightness frame amount))
|
||||
13
sexp_effects/effects/color-adjust.sexp
Normal file
13
sexp_effects/effects/color-adjust.sexp
Normal file
@@ -0,0 +1,13 @@
|
||||
;; Color adjustment effect - replaces TRANSFORM node
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect color-adjust
|
||||
:params (
|
||||
(brightness :type int :default 0 :range [-255 255] :desc "Brightness adjustment")
|
||||
(contrast :type float :default 1 :range [0 3] :desc "Contrast multiplier")
|
||||
(saturation :type float :default 1 :range [0 2] :desc "Saturation multiplier")
|
||||
)
|
||||
(-> frame
|
||||
(color_ops:adjust-brightness brightness)
|
||||
(color_ops:adjust-contrast contrast)
|
||||
(color_ops:adjust-saturation saturation)))
|
||||
13
sexp_effects/effects/color_cycle.sexp
Normal file
13
sexp_effects/effects/color_cycle.sexp
Normal file
@@ -0,0 +1,13 @@
|
||||
;; Color Cycle effect - animated hue rotation
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect color_cycle
|
||||
:params (
|
||||
(speed :type int :default 1 :range [0 10])
|
||||
)
|
||||
(let ((shift (* t speed 360)))
|
||||
(map-pixels frame
|
||||
(lambda (x y c)
|
||||
(let* ((hsv (rgb->hsv c))
|
||||
(new-h (mod (+ (first hsv) shift) 360)))
|
||||
(hsv->rgb (list new-h (nth hsv 1) (nth hsv 2))))))))
|
||||
9
sexp_effects/effects/contrast.sexp
Normal file
9
sexp_effects/effects/contrast.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Contrast effect - adjusts image contrast
|
||||
;; Uses vectorized adjust primitive for fast processing
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect contrast
|
||||
:params (
|
||||
(amount :type int :default 1 :range [0.5 3])
|
||||
)
|
||||
(color_ops:adjust-contrast frame amount))
|
||||
30
sexp_effects/effects/crt.sexp
Normal file
30
sexp_effects/effects/crt.sexp
Normal file
@@ -0,0 +1,30 @@
|
||||
;; CRT effect - old monitor simulation
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect crt
|
||||
:params (
|
||||
(line_spacing :type int :default 2 :range [1 10])
|
||||
(line_opacity :type float :default 0.3 :range [0 1])
|
||||
(vignette_amount :type float :default 0.2)
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (/ w 2))
|
||||
(cy (/ h 2))
|
||||
(max-dist (sqrt (+ (* cx cx) (* cy cy)))))
|
||||
(map-pixels frame
|
||||
(lambda (x y c)
|
||||
(let* (;; Scanline darkening
|
||||
(scanline-factor (if (= 0 (mod y line_spacing))
|
||||
(- 1 line_opacity)
|
||||
1))
|
||||
;; Vignette
|
||||
(dx (- x cx))
|
||||
(dy (- y cy))
|
||||
(dist (sqrt (+ (* dx dx) (* dy dy))))
|
||||
(vignette-factor (- 1 (* (/ dist max-dist) vignette_amount)))
|
||||
;; Combined
|
||||
(factor (* scanline-factor vignette-factor)))
|
||||
(rgb (* (red c) factor)
|
||||
(* (green c) factor)
|
||||
(* (blue c) factor)))))))
|
||||
14
sexp_effects/effects/datamosh.sexp
Normal file
14
sexp_effects/effects/datamosh.sexp
Normal file
@@ -0,0 +1,14 @@
|
||||
;; Datamosh effect - glitch block corruption
|
||||
|
||||
(define-effect datamosh
|
||||
:params (
|
||||
(block_size :type int :default 32 :range [8 128])
|
||||
(corruption :type float :default 0.3 :range [0 1])
|
||||
(max_offset :type int :default 50 :range [0 200])
|
||||
(color_corrupt :type bool :default true)
|
||||
)
|
||||
;; Get previous frame from state, or use current frame if none
|
||||
(let ((prev (state-get "prev_frame" frame)))
|
||||
(begin
|
||||
(state-set "prev_frame" (copy frame))
|
||||
(datamosh frame prev block_size corruption max_offset color_corrupt))))
|
||||
19
sexp_effects/effects/echo.sexp
Normal file
19
sexp_effects/effects/echo.sexp
Normal file
@@ -0,0 +1,19 @@
|
||||
;; Echo effect - motion trails using frame buffer
|
||||
(require-primitives "blending")
|
||||
|
||||
(define-effect echo
|
||||
:params (
|
||||
(num_echoes :type int :default 4 :range [1 20])
|
||||
(decay :type float :default 0.5 :range [0 1])
|
||||
)
|
||||
(let* ((buffer (state-get 'buffer (list)))
|
||||
(new-buffer (take (cons frame buffer) (+ num_echoes 1))))
|
||||
(begin
|
||||
(state-set 'buffer new-buffer)
|
||||
;; Blend frames with decay
|
||||
(if (< (length new-buffer) 2)
|
||||
frame
|
||||
(let ((result (copy frame)))
|
||||
;; Simple blend of first two frames for now
|
||||
;; Full version would fold over all frames
|
||||
(blending:blend-images frame (nth new-buffer 1) (* decay 0.5)))))))
|
||||
9
sexp_effects/effects/edge_detect.sexp
Normal file
9
sexp_effects/effects/edge_detect.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Edge detection effect - highlights edges
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect edge_detect
|
||||
:params (
|
||||
(low :type int :default 50 :range [10 100])
|
||||
(high :type int :default 150 :range [50 300])
|
||||
)
|
||||
(image:edge-detect frame low high))
|
||||
13
sexp_effects/effects/emboss.sexp
Normal file
13
sexp_effects/effects/emboss.sexp
Normal file
@@ -0,0 +1,13 @@
|
||||
;; Emboss effect - creates raised/3D appearance
|
||||
(require-primitives "blending")
|
||||
|
||||
(define-effect emboss
|
||||
:params (
|
||||
(strength :type int :default 1 :range [0.5 3])
|
||||
(blend :type float :default 0.3 :range [0 1])
|
||||
)
|
||||
(let* ((kernel (list (list (- strength) (- strength) 0)
|
||||
(list (- strength) 1 strength)
|
||||
(list 0 strength strength)))
|
||||
(embossed (convolve frame kernel)))
|
||||
(blending:blend-images embossed frame blend)))
|
||||
19
sexp_effects/effects/film_grain.sexp
Normal file
19
sexp_effects/effects/film_grain.sexp
Normal file
@@ -0,0 +1,19 @@
|
||||
;; Film Grain effect - adds film grain texture
|
||||
(require-primitives "core")
|
||||
|
||||
(define-effect film_grain
|
||||
:params (
|
||||
(intensity :type float :default 0.2 :range [0 1])
|
||||
(colored :type bool :default false)
|
||||
)
|
||||
(let ((grain-amount (* intensity 50)))
|
||||
(map-pixels frame
|
||||
(lambda (x y c)
|
||||
(if colored
|
||||
(rgb (clamp (+ (red c) (gaussian 0 grain-amount)) 0 255)
|
||||
(clamp (+ (green c) (gaussian 0 grain-amount)) 0 255)
|
||||
(clamp (+ (blue c) (gaussian 0 grain-amount)) 0 255))
|
||||
(let ((n (gaussian 0 grain-amount)))
|
||||
(rgb (clamp (+ (red c) n) 0 255)
|
||||
(clamp (+ (green c) n) 0 255)
|
||||
(clamp (+ (blue c) n) 0 255))))))))
|
||||
16
sexp_effects/effects/fisheye.sexp
Normal file
16
sexp_effects/effects/fisheye.sexp
Normal file
@@ -0,0 +1,16 @@
|
||||
;; Fisheye effect - barrel/pincushion lens distortion
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect fisheye
|
||||
:params (
|
||||
(strength :type float :default 0.3 :range [-1 1])
|
||||
(center_x :type float :default 0.5 :range [0 1])
|
||||
(center_y :type float :default 0.5 :range [0 1])
|
||||
(zoom_correct :type bool :default true)
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (* w center_x))
|
||||
(cy (* h center_y))
|
||||
(coords (geometry:fisheye-coords w h strength cx cy zoom_correct)))
|
||||
(geometry:remap frame (geometry:coords-x coords) (geometry:coords-y coords))))
|
||||
16
sexp_effects/effects/flip.sexp
Normal file
16
sexp_effects/effects/flip.sexp
Normal file
@@ -0,0 +1,16 @@
|
||||
;; Flip effect - flips image horizontally or vertically
|
||||
(require-primitives "geometry")
|
||||
|
||||
(define-effect flip
|
||||
:params (
|
||||
(horizontal :type bool :default true)
|
||||
(vertical :type bool :default false)
|
||||
)
|
||||
(let ((result frame))
|
||||
(if horizontal
|
||||
(set! result (geometry:flip-img result "horizontal"))
|
||||
nil)
|
||||
(if vertical
|
||||
(set! result (geometry:flip-img result "vertical"))
|
||||
nil)
|
||||
result))
|
||||
7
sexp_effects/effects/grayscale.sexp
Normal file
7
sexp_effects/effects/grayscale.sexp
Normal file
@@ -0,0 +1,7 @@
|
||||
;; Grayscale effect - converts to grayscale
|
||||
;; Uses vectorized mix-gray primitive for fast processing
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect grayscale
|
||||
:params ()
|
||||
(image:grayscale frame))
|
||||
12
sexp_effects/effects/hue_shift.sexp
Normal file
12
sexp_effects/effects/hue_shift.sexp
Normal file
@@ -0,0 +1,12 @@
|
||||
;; Hue shift effect - rotates hue values
|
||||
;; Uses vectorized shift-hsv primitive for fast processing
|
||||
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect hue_shift
|
||||
:params (
|
||||
(degrees :type int :default 0 :range [0 360])
|
||||
(speed :type int :default 0 :desc "rotation per second")
|
||||
)
|
||||
(let ((shift (+ degrees (* speed t))))
|
||||
(color_ops:shift-hsv frame shift 1 1)))
|
||||
9
sexp_effects/effects/invert.sexp
Normal file
9
sexp_effects/effects/invert.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Invert effect - inverts all colors
|
||||
;; Uses vectorized invert-img primitive for fast processing
|
||||
;; amount param: 0 = no invert, 1 = full invert (threshold at 0.5)
|
||||
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect invert
|
||||
:params ((amount :type float :default 1 :range [0 1]))
|
||||
(if (> amount 0.5) (color_ops:invert-img frame) frame))
|
||||
20
sexp_effects/effects/kaleidoscope.sexp
Normal file
20
sexp_effects/effects/kaleidoscope.sexp
Normal file
@@ -0,0 +1,20 @@
|
||||
;; Kaleidoscope effect - mandala-like symmetry patterns
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect kaleidoscope
|
||||
:params (
|
||||
(segments :type int :default 6 :range [3 16])
|
||||
(rotation :type int :default 0 :range [0 360])
|
||||
(rotation_speed :type int :default 0 :range [-180 180])
|
||||
(center_x :type float :default 0.5 :range [0 1])
|
||||
(center_y :type float :default 0.5 :range [0 1])
|
||||
(zoom :type int :default 1 :range [0.5 3])
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (* w center_x))
|
||||
(cy (* h center_y))
|
||||
;; Total rotation including time-based animation
|
||||
(total_rot (+ rotation (* rotation_speed (or _time 0))))
|
||||
(coords (geometry:kaleidoscope-coords w h segments total_rot cx cy zoom)))
|
||||
(geometry:remap frame (geometry:coords-x coords) (geometry:coords-y coords))))
|
||||
36
sexp_effects/effects/layer.sexp
Normal file
36
sexp_effects/effects/layer.sexp
Normal file
@@ -0,0 +1,36 @@
|
||||
;; Layer effect - composite overlay over background at position
|
||||
;; Streaming-compatible: frame is background, overlay is foreground
|
||||
;; Usage: (layer background overlay :x 10 :y 20 :opacity 0.8)
|
||||
;;
|
||||
;; Params:
|
||||
;; overlay - frame to composite on top
|
||||
;; x, y - position to place overlay
|
||||
;; opacity - blend amount (0-1)
|
||||
;; mode - blend mode (alpha, multiply, screen, etc.)
|
||||
|
||||
(require-primitives "image" "blending" "core")
|
||||
|
||||
(define-effect layer
|
||||
:params (
|
||||
(overlay :type frame :default nil)
|
||||
(x :type int :default 0)
|
||||
(y :type int :default 0)
|
||||
(opacity :type float :default 1.0)
|
||||
(mode :type string :default "alpha")
|
||||
)
|
||||
(if (core:is-nil overlay)
|
||||
frame
|
||||
(let [bg (copy frame)
|
||||
fg overlay
|
||||
fg-w (image:width fg)
|
||||
fg-h (image:height fg)]
|
||||
(if (= opacity 1.0)
|
||||
;; Simple paste
|
||||
(paste bg fg x y)
|
||||
;; Blend with opacity
|
||||
(let [blended (if (= mode "alpha")
|
||||
(blending:blend-images (image:crop bg x y fg-w fg-h) fg opacity)
|
||||
(blending:blend-images (image:crop bg x y fg-w fg-h)
|
||||
(blending:blend-mode (image:crop bg x y fg-w fg-h) fg mode)
|
||||
opacity))]
|
||||
(paste bg blended x y))))))
|
||||
33
sexp_effects/effects/mirror.sexp
Normal file
33
sexp_effects/effects/mirror.sexp
Normal file
@@ -0,0 +1,33 @@
|
||||
;; Mirror effect - mirrors half of image
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect mirror
|
||||
:params (
|
||||
(mode :type string :default "left_right")
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(hw (floor (/ w 2)))
|
||||
(hh (floor (/ h 2))))
|
||||
(cond
|
||||
((= mode "left_right")
|
||||
(let ((left (image:crop frame 0 0 hw h))
|
||||
(result (copy frame)))
|
||||
(paste result (geometry:flip-img left "horizontal") hw 0)))
|
||||
|
||||
((= mode "right_left")
|
||||
(let ((right (image:crop frame hw 0 hw h))
|
||||
(result (copy frame)))
|
||||
(paste result (geometry:flip-img right "horizontal") 0 0)))
|
||||
|
||||
((= mode "top_bottom")
|
||||
(let ((top (image:crop frame 0 0 w hh))
|
||||
(result (copy frame)))
|
||||
(paste result (geometry:flip-img top "vertical") 0 hh)))
|
||||
|
||||
((= mode "bottom_top")
|
||||
(let ((bottom (image:crop frame 0 hh w hh))
|
||||
(result (copy frame)))
|
||||
(paste result (geometry:flip-img bottom "vertical") 0 0)))
|
||||
|
||||
(else frame))))
|
||||
23
sexp_effects/effects/neon_glow.sexp
Normal file
23
sexp_effects/effects/neon_glow.sexp
Normal file
@@ -0,0 +1,23 @@
|
||||
;; Neon Glow effect - glowing edge effect
|
||||
(require-primitives "image" "blending")
|
||||
|
||||
(define-effect neon_glow
|
||||
:params (
|
||||
(edge_low :type int :default 50 :range [10 200])
|
||||
(edge_high :type int :default 150 :range [50 300])
|
||||
(glow_radius :type int :default 15 :range [1 50])
|
||||
(glow_intensity :type int :default 2 :range [0.5 5])
|
||||
(background :type float :default 0.3 :range [0 1])
|
||||
)
|
||||
(let* ((edge-img (image:edge-detect frame edge_low edge_high))
|
||||
(glow (image:blur edge-img glow_radius))
|
||||
;; Intensify the glow
|
||||
(bright-glow (map-pixels glow
|
||||
(lambda (x y c)
|
||||
(rgb (clamp (* (red c) glow_intensity) 0 255)
|
||||
(clamp (* (green c) glow_intensity) 0 255)
|
||||
(clamp (* (blue c) glow_intensity) 0 255))))))
|
||||
(blending:blend-mode (blending:blend-images frame (make-image (image:width frame) (image:height frame) (list 0 0 0))
|
||||
(- 1 background))
|
||||
bright-glow
|
||||
"screen")))
|
||||
8
sexp_effects/effects/noise.sexp
Normal file
8
sexp_effects/effects/noise.sexp
Normal file
@@ -0,0 +1,8 @@
|
||||
;; Noise effect - adds random noise
|
||||
;; Uses vectorized add-noise primitive for fast processing
|
||||
|
||||
(define-effect noise
|
||||
:params (
|
||||
(amount :type int :default 20 :range [0 100])
|
||||
)
|
||||
(add-noise frame amount))
|
||||
24
sexp_effects/effects/outline.sexp
Normal file
24
sexp_effects/effects/outline.sexp
Normal file
@@ -0,0 +1,24 @@
|
||||
;; Outline effect - shows only edges
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect outline
|
||||
:params (
|
||||
(thickness :type int :default 2 :range [1 10])
|
||||
(threshold :type int :default 100 :range [20 300])
|
||||
(color :type list :default (list 0 0 0)
|
||||
)
|
||||
(fill_mode "original"))
|
||||
(let* ((edge-img (image:edge-detect frame (/ threshold 2) threshold))
|
||||
(dilated (if (> thickness 1)
|
||||
(dilate edge-img thickness)
|
||||
edge-img))
|
||||
(base (cond
|
||||
((= fill_mode "original") (copy frame))
|
||||
((= fill_mode "white") (make-image (image:width frame) (image:height frame) (list 255 255 255)))
|
||||
(else (make-image (image:width frame) (image:height frame) (list 0 0 0))))))
|
||||
(map-pixels base
|
||||
(lambda (x y c)
|
||||
(let ((edge-val (luminance (pixel dilated x y))))
|
||||
(if (> edge-val 128)
|
||||
color
|
||||
c))))))
|
||||
13
sexp_effects/effects/pixelate.sexp
Normal file
13
sexp_effects/effects/pixelate.sexp
Normal file
@@ -0,0 +1,13 @@
|
||||
;; Pixelate effect - creates blocky pixels
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect pixelate
|
||||
:params (
|
||||
(block_size :type int :default 8 :range [2 64])
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(small-w (max 1 (floor (/ w block_size))))
|
||||
(small-h (max 1 (floor (/ h block_size))))
|
||||
(small (image:resize frame small-w small-h "area")))
|
||||
(image:resize small w h "nearest")))
|
||||
11
sexp_effects/effects/pixelsort.sexp
Normal file
11
sexp_effects/effects/pixelsort.sexp
Normal file
@@ -0,0 +1,11 @@
|
||||
;; Pixelsort effect - glitch art pixel sorting
|
||||
|
||||
(define-effect pixelsort
|
||||
:params (
|
||||
(sort_by :type string :default "lightness")
|
||||
(threshold_low :type int :default 50 :range [0 255])
|
||||
(threshold_high :type int :default 200 :range [0 255])
|
||||
(angle :type int :default 0 :range [0 180])
|
||||
(reverse :type bool :default false)
|
||||
)
|
||||
(pixelsort frame sort_by threshold_low threshold_high angle reverse))
|
||||
8
sexp_effects/effects/posterize.sexp
Normal file
8
sexp_effects/effects/posterize.sexp
Normal file
@@ -0,0 +1,8 @@
|
||||
;; Posterize effect - reduces color levels
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect posterize
|
||||
:params (
|
||||
(levels :type int :default 8 :range [2 32])
|
||||
)
|
||||
(color_ops:posterize frame levels))
|
||||
11
sexp_effects/effects/resize-frame.sexp
Normal file
11
sexp_effects/effects/resize-frame.sexp
Normal file
@@ -0,0 +1,11 @@
|
||||
;; Resize effect - replaces RESIZE node
|
||||
;; Note: uses target-w/target-h to avoid conflict with width/height primitives
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect resize-frame
|
||||
:params (
|
||||
(target-w :type int :default 640 :desc "Target width in pixels")
|
||||
(target-h :type int :default 480 :desc "Target height in pixels")
|
||||
(mode :type string :default "linear" :choices [linear nearest area] :desc "Interpolation mode")
|
||||
)
|
||||
(image:resize frame target-w target-h mode))
|
||||
13
sexp_effects/effects/rgb_split.sexp
Normal file
13
sexp_effects/effects/rgb_split.sexp
Normal file
@@ -0,0 +1,13 @@
|
||||
;; RGB Split effect - chromatic aberration
|
||||
|
||||
(define-effect rgb_split
|
||||
:params (
|
||||
(offset_x :type int :default 10 :range [-50 50])
|
||||
(offset_y :type int :default 0 :range [-50 50])
|
||||
)
|
||||
(let* ((r (channel frame 0))
|
||||
(g (channel frame 1))
|
||||
(b (channel frame 2))
|
||||
(r-shifted (translate (merge-channels r r r) offset_x offset_y))
|
||||
(b-shifted (translate (merge-channels b b b) (- offset_x) (- offset_y))))
|
||||
(merge-channels (channel r-shifted 0) g (channel b-shifted 0))))
|
||||
19
sexp_effects/effects/ripple.sexp
Normal file
19
sexp_effects/effects/ripple.sexp
Normal file
@@ -0,0 +1,19 @@
|
||||
;; Ripple effect - radial wave distortion from center
|
||||
(require-primitives "geometry" "image" "math")
|
||||
|
||||
(define-effect ripple
|
||||
:params (
|
||||
(frequency :type int :default 5 :range [1 20])
|
||||
(amplitude :type int :default 10 :range [0 50])
|
||||
(center_x :type float :default 0.5 :range [0 1])
|
||||
(center_y :type float :default 0.5 :range [0 1])
|
||||
(decay :type int :default 1 :range [0 5])
|
||||
(speed :type int :default 1 :range [0 10])
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (* w center_x))
|
||||
(cy (* h center_y))
|
||||
(phase (* (or t 0) speed 2 pi))
|
||||
(coords (geometry:ripple-displace w h frequency amplitude cx cy decay phase)))
|
||||
(geometry:remap frame (geometry:coords-x coords) (geometry:coords-y coords))))
|
||||
11
sexp_effects/effects/rotate.sexp
Normal file
11
sexp_effects/effects/rotate.sexp
Normal file
@@ -0,0 +1,11 @@
|
||||
;; Rotate effect - rotates image
|
||||
|
||||
(require-primitives "geometry")
|
||||
|
||||
(define-effect rotate
|
||||
:params (
|
||||
(angle :type int :default 0 :range [-360 360])
|
||||
(speed :type int :default 0 :desc "rotation per second")
|
||||
)
|
||||
(let ((total-angle (+ angle (* speed t))))
|
||||
(geometry:rotate-img frame total-angle)))
|
||||
9
sexp_effects/effects/saturation.sexp
Normal file
9
sexp_effects/effects/saturation.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Saturation effect - adjusts color saturation
|
||||
;; Uses vectorized shift-hsv primitive for fast processing
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect saturation
|
||||
:params (
|
||||
(amount :type int :default 1 :range [0 3])
|
||||
)
|
||||
(color_ops:adjust-saturation frame amount))
|
||||
15
sexp_effects/effects/scanlines.sexp
Normal file
15
sexp_effects/effects/scanlines.sexp
Normal file
@@ -0,0 +1,15 @@
|
||||
;; Scanlines effect - VHS-style horizontal line shifting
|
||||
(require-primitives "core")
|
||||
|
||||
(define-effect scanlines
|
||||
:params (
|
||||
(amplitude :type int :default 10 :range [0 100])
|
||||
(frequency :type int :default 10 :range [1 100])
|
||||
(randomness :type float :default 0.5 :range [0 1])
|
||||
)
|
||||
(map-rows frame
|
||||
(lambda (y row)
|
||||
(let* ((sine-shift (* amplitude (sin (/ (* y 6.28) (max 1 frequency)))))
|
||||
(rand-shift (core:rand-range (- amplitude) amplitude))
|
||||
(shift (floor (lerp sine-shift rand-shift randomness))))
|
||||
(roll row shift 0)))))
|
||||
7
sexp_effects/effects/sepia.sexp
Normal file
7
sexp_effects/effects/sepia.sexp
Normal file
@@ -0,0 +1,7 @@
|
||||
;; Sepia effect - applies sepia tone
|
||||
;; Classic warm vintage look
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect sepia
|
||||
:params ()
|
||||
(color_ops:sepia frame))
|
||||
8
sexp_effects/effects/sharpen.sexp
Normal file
8
sexp_effects/effects/sharpen.sexp
Normal file
@@ -0,0 +1,8 @@
|
||||
;; Sharpen effect - sharpens edges
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect sharpen
|
||||
:params (
|
||||
(amount :type int :default 1 :range [0 5])
|
||||
)
|
||||
(image:sharpen frame amount))
|
||||
16
sexp_effects/effects/strobe.sexp
Normal file
16
sexp_effects/effects/strobe.sexp
Normal file
@@ -0,0 +1,16 @@
|
||||
;; Strobe effect - holds frames for choppy look
|
||||
(require-primitives "core")
|
||||
|
||||
(define-effect strobe
|
||||
:params (
|
||||
(frame_rate :type int :default 12 :range [1 60])
|
||||
)
|
||||
(let* ((held (state-get 'held nil))
|
||||
(held-until (state-get 'held-until 0))
|
||||
(frame-duration (/ 1 frame_rate)))
|
||||
(if (or (core:is-nil held) (>= t held-until))
|
||||
(begin
|
||||
(state-set 'held (copy frame))
|
||||
(state-set 'held-until (+ t frame-duration))
|
||||
frame)
|
||||
held)))
|
||||
17
sexp_effects/effects/swirl.sexp
Normal file
17
sexp_effects/effects/swirl.sexp
Normal file
@@ -0,0 +1,17 @@
|
||||
;; Swirl effect - spiral vortex distortion
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect swirl
|
||||
:params (
|
||||
(strength :type int :default 1 :range [-10 10])
|
||||
(radius :type float :default 0.5 :range [0.1 2])
|
||||
(center_x :type float :default 0.5 :range [0 1])
|
||||
(center_y :type float :default 0.5 :range [0 1])
|
||||
(falloff :type string :default "quadratic")
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (* w center_x))
|
||||
(cy (* h center_y))
|
||||
(coords (geometry:swirl-coords w h strength radius cx cy falloff)))
|
||||
(geometry:remap frame (geometry:coords-x coords) (geometry:coords-y coords))))
|
||||
9
sexp_effects/effects/threshold.sexp
Normal file
9
sexp_effects/effects/threshold.sexp
Normal file
@@ -0,0 +1,9 @@
|
||||
;; Threshold effect - converts to black and white
|
||||
(require-primitives "color_ops")
|
||||
|
||||
(define-effect threshold
|
||||
:params (
|
||||
(level :type int :default 128 :range [0 255])
|
||||
(invert :type bool :default false)
|
||||
)
|
||||
(color_ops:threshold frame level invert))
|
||||
29
sexp_effects/effects/tile_grid.sexp
Normal file
29
sexp_effects/effects/tile_grid.sexp
Normal file
@@ -0,0 +1,29 @@
|
||||
;; Tile Grid effect - tiles image in grid
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect tile_grid
|
||||
:params (
|
||||
(rows :type int :default 2 :range [1 10])
|
||||
(cols :type int :default 2 :range [1 10])
|
||||
(gap :type int :default 0 :range [0 50])
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(tile-w (floor (/ (- w (* gap (- cols 1))) cols)))
|
||||
(tile-h (floor (/ (- h (* gap (- rows 1))) rows)))
|
||||
(tile (image:resize frame tile-w tile-h "area"))
|
||||
(result (make-image w h (list 0 0 0))))
|
||||
(begin
|
||||
;; Manually place tiles using nested iteration
|
||||
;; This is a simplified version - full version would loop
|
||||
(paste result tile 0 0)
|
||||
(if (> cols 1)
|
||||
(paste result tile (+ tile-w gap) 0)
|
||||
nil)
|
||||
(if (> rows 1)
|
||||
(paste result tile 0 (+ tile-h gap))
|
||||
nil)
|
||||
(if (and (> cols 1) (> rows 1))
|
||||
(paste result tile (+ tile-w gap) (+ tile-h gap))
|
||||
nil)
|
||||
result)))
|
||||
20
sexp_effects/effects/trails.sexp
Normal file
20
sexp_effects/effects/trails.sexp
Normal file
@@ -0,0 +1,20 @@
|
||||
;; Trails effect - persistent motion trails
|
||||
(require-primitives "image" "blending")
|
||||
|
||||
(define-effect trails
|
||||
:params (
|
||||
(persistence :type float :default 0.8 :range [0 0.99])
|
||||
)
|
||||
(let* ((buffer (state-get 'buffer nil))
|
||||
(current frame))
|
||||
(if (= buffer nil)
|
||||
(begin
|
||||
(state-set 'buffer (copy frame))
|
||||
frame)
|
||||
(let* ((faded (blending:blend-images buffer
|
||||
(make-image (image:width frame) (image:height frame) (list 0 0 0))
|
||||
(- 1 persistence)))
|
||||
(result (blending:blend-mode faded current "lighten")))
|
||||
(begin
|
||||
(state-set 'buffer result)
|
||||
result)))))
|
||||
23
sexp_effects/effects/vignette.sexp
Normal file
23
sexp_effects/effects/vignette.sexp
Normal file
@@ -0,0 +1,23 @@
|
||||
;; Vignette effect - darkens corners
|
||||
(require-primitives "image")
|
||||
|
||||
(define-effect vignette
|
||||
:params (
|
||||
(strength :type float :default 0.5 :range [0 1])
|
||||
(radius :type int :default 1 :range [0.5 2])
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
(cx (/ w 2))
|
||||
(cy (/ h 2))
|
||||
(max-dist (* (sqrt (+ (* cx cx) (* cy cy))) radius)))
|
||||
(map-pixels frame
|
||||
(lambda (x y c)
|
||||
(let* ((dx (- x cx))
|
||||
(dy (- y cy))
|
||||
(dist (sqrt (+ (* dx dx) (* dy dy))))
|
||||
(factor (- 1 (* (/ dist max-dist) strength)))
|
||||
(factor (clamp factor 0 1)))
|
||||
(rgb (* (red c) factor)
|
||||
(* (green c) factor)
|
||||
(* (blue c) factor)))))))
|
||||
22
sexp_effects/effects/wave.sexp
Normal file
22
sexp_effects/effects/wave.sexp
Normal file
@@ -0,0 +1,22 @@
|
||||
;; Wave effect - sine wave displacement distortion
|
||||
(require-primitives "geometry" "image")
|
||||
|
||||
(define-effect wave
|
||||
:params (
|
||||
(amplitude :type int :default 10 :range [0 100])
|
||||
(wavelength :type int :default 50 :range [10 500])
|
||||
(speed :type int :default 1 :range [0 10])
|
||||
(direction :type string :default "horizontal")
|
||||
)
|
||||
(let* ((w (image:width frame))
|
||||
(h (image:height frame))
|
||||
;; Use _time for animation phase
|
||||
(phase (* (or _time 0) speed 2 pi))
|
||||
;; Calculate frequency: waves per dimension
|
||||
(freq (/ (if (= direction "vertical") w h) wavelength))
|
||||
(axis (cond
|
||||
((= direction "horizontal") "x")
|
||||
((= direction "vertical") "y")
|
||||
(else "both")))
|
||||
(coords (geometry:wave-coords w h axis freq amplitude phase)))
|
||||
(geometry:remap frame (geometry:coords-x coords) (geometry:coords-y coords))))
|
||||
8
sexp_effects/effects/zoom.sexp
Normal file
8
sexp_effects/effects/zoom.sexp
Normal file
@@ -0,0 +1,8 @@
|
||||
;; Zoom effect - zooms in/out from center
|
||||
(require-primitives "geometry")
|
||||
|
||||
(define-effect zoom
|
||||
:params (
|
||||
(amount :type int :default 1 :range [0.1 5])
|
||||
)
|
||||
(geometry:scale-img frame amount amount))
|
||||
Reference in New Issue
Block a user