# /// script # requires-python = ">=3.10" # dependencies = ["numpy", "opencv-python"] # /// """ @effect bloom @version 1.0.0 @author artdag @description Bloom effect. Creates a soft glow around bright areas, simulating camera lens bloom. Great for dreamy or ethereal looks. @param intensity float @range 0 2 @default 0.5 Bloom brightness. @param threshold int @range 0 255 @default 200 Brightness threshold for bloom (pixels above this glow). @param radius int @range 1 50 @default 15 Blur radius for the glow. @param soft_threshold bool @default true Use soft threshold (gradual) vs hard threshold. @param color_tint list @default [255, 255, 255] Tint color for the bloom. @example (effect bloom :intensity 0.7 :threshold 180) @example ;; Warm bloom (effect bloom :intensity 0.6 :color_tint [255 200 150]) """ import numpy as np import cv2 def process_frame(frame: np.ndarray, params: dict, state: dict) -> tuple: """ Apply bloom effect to a video frame. Args: frame: Input frame as numpy array (H, W, 3) RGB uint8 params: Effect parameters - intensity: bloom brightness (default 0.5) - threshold: brightness cutoff (default 200) - radius: blur radius (default 15) - soft_threshold: gradual vs hard (default True) - color_tint: RGB tint (default white) state: Persistent state dict Returns: Tuple of (processed_frame, new_state) """ intensity = params.get("intensity", 0.5) threshold = int(params.get("threshold", 200)) radius = max(1, int(params.get("radius", 15))) soft_threshold = params.get("soft_threshold", True) color_tint = params.get("color_tint", [255, 255, 255]) if state is None: state = {} if intensity <= 0: return frame, state # Convert to float result = frame.astype(np.float32) # Get brightness (luminance) lum = 0.299 * result[:, :, 0] + 0.587 * result[:, :, 1] + 0.114 * result[:, :, 2] # Create bloom mask if soft_threshold: # Soft threshold - gradual falloff bloom_mask = np.clip((lum - threshold) / (255 - threshold + 1e-6), 0, 1) else: # Hard threshold bloom_mask = (lum > threshold).astype(np.float32) # Extract bright areas bloom = result * bloom_mask[:, :, np.newaxis] # Apply blur to create glow ksize = radius * 2 + 1 bloom = cv2.GaussianBlur(bloom, (ksize, ksize), 0) # Apply color tint if isinstance(color_tint, (list, tuple)) and len(color_tint) >= 3: tint = np.array(color_tint[:3], dtype=np.float32) / 255.0 for c in range(3): bloom[:, :, c] *= tint[c] # Add bloom to original (screen blend) result = result + bloom * intensity return np.clip(result, 0, 255).astype(np.uint8), state