Install
$ agentstack add skill-isaacrowntree-color-grade-ai-color-grade-ai ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Color Grade AI
Generate targeted .cube 3D LUTs for color correction. Auto-analyze frames and recommend DaVinci Resolve-style node chain settings. Interactive in-browser preview with Preact.
Quick Start
# Generate a correction LUT (presets defined in presets.yml)
ruby generate_lut.rb [--strength=0.0-1.0]
# Bake multiple presets into a single .cube LUT
ruby generate_chain_lut.rb ...
# Auto-analyze a frame and get node recommendations
python3 auto_grade.py
# Compare reference vs output and get adjustment suggestions
python3 match_grade.py
# Analyze specific regions for color stats
ruby analyze_frame.rb [label]
# Serve the interactive preview
python3 -m http.server 8080
# Open http://localhost:8080/preview.html
Auto-Grade Analysis
auto_grade.py analyzes a Rec.709 frame (post-conversion LUT) and recommends correction values for each node using classical color science:
| Node | Method | Target | |------|--------|--------| | Contrast/Exposure | Luminance histogram percentiles | Median ~0.45, dynamic range ~0.85 | | White Balance | Shades of Gray (Minkowski p=6) + White Patch blend | RGB gains near 1.0 | | Skin Tone | HSV-based skin detection, I-line targeting | Hue ~20° (peach) | | Saturation | Hasler-Susstrunk colorfulness metric | Colorfulness 35-55 | | Black Level | Bottom 5% luminance analysis + noise floor | Black point
Useful for matching grades across clips or iterating toward a target look.
## Interactive Preview (preview.html)
Browser-based node chain previewer using Preact + HTM (~4KB). Applies .cube LUTs on canvas in real-time.
Features:
- **Drag-and-drop** any frame (raw S-Log3 or converted)
- **Node 1: Conversion LUT** — add your own .cube files (not included in repo)
- **Nodes 2-6: Correction chain** — dropdown presets + strength sliders
- **Creative presets** — one-click curated looks (Studio Dance, Studio Clean, Studio Ambient, Studio Gold, Studio Film)
- **S-Gamut3 → Cine compensation** toggle for gamut mismatch
- **Bypass/reset** all nodes instantly
- **URL parameters** — deep-link to a specific state: `?image=frame.png&lut=path/to.cube&preset=studio_gold`
Correction LUTs are committed in `correction_luts/`. Conversion LUTs are user-provided (gitignored in `luts/`).
## Config-Driven Presets
All LUT types are defined in `presets.yml`. Each preset is a pipeline of ordered processing steps. Adding a new LUT type means adding a YAML entry — no Ruby code changes needed.
Available step types: `exposure`, `highlight_protect`, `black_crush`, `hue_desat`, `skin_correction`, `shadow_sat_boost`, `skin_highlight`, `skin_rolloff`, `global_highlight_desat`, `rgb_rebalance`, `global_sat`.
## Available LUT Types
### Correction LUTs (apply after conversion)
| Type | What it fixes |
|------|--------------|
| `night_warm_fix` | All-in-one for underexposed warm/red scenes. ~1 stop lift + skin hue shift + black crush. |
| `night_purple_fix` | All-in-one for underexposed purple/magenta stage lighting. RGB rebalancing + lift + desat + skin fix. |
| `yellow_fix` | Warm amber/yellow cast from stage lighting. H=10-60, 55% desat. |
| `red_skin_fix` | Red/flushed skin from warm practicals. Hue shift to peach, skin-only targeting. |
| `pink_cast_fix` | Pink/magenta cast from stage lighting. Gentle RGB rebalance + magenta desat. |
| `overexposure_fix` | Scene-wide ~1 stop reduction with highlight rolloff. |
| `underexposure_fix` | Scene-wide ~1.2 stop lift with shadow recovery. |
| `black_crush` | Crushes milky/lifted blacks below 12% to true black. |
| `skin_highlight_fix` | Subtle skin-only highlight rolloff above 70% luminance. |
| `golden_warm` | Strong golden warm shift via RGB rebalance (R:1.20, G:1.00, B:0.80). For rich warm cinematic looks. |
| `cinema_dark` | Deep moody contrast with gamma 1.45, shadow lift 0.02, and knee compression (0.72-0.90). |
### Node Chain Building Blocks
| Type | Node | What it does |
|------|------|-------------|
| `studio_punch` | Contrast | Subtle contrast boost for well-lit interiors |
| `film_contrast` | Contrast | Stronger filmic contrast with deeper shadows |
| `flat_lift` | Contrast | Lifts shadows for softer, more open look |
| `warm_shift` | Temperature | Subtle warm shift via RGB rebalance |
| `cool_shift` | Temperature | Subtle cool shift via RGB rebalance |
| `led_green_fix` | Temperature | Fixes green tint from LED/fluorescent lights |
| `sat_boost` | Saturation | Global +15% saturation boost |
| `golden_warm` | Temperature | Strong golden warm shift (R:1.20, G:1.00, B:0.80) |
| `sat_reduce` | Saturation | Global -15% saturation reduction |
| `sgamut3_to_cine` | Gamut | S-Gamut3 → Cine compensation (desat ~12%) |
| `cinema_dark` | Contrast | Deep moody contrast (gamma 1.45, shadow lift, knee compression) |
| `black_lift` | Black Level | Lifts blacks for vintage/faded look |
### Creative Presets (node chain combinations)
| Preset | Look | Chain |
|--------|------|-------|
| Studio Clean | Natural bright | studio_punch(50%) + sat_boost(50%) |
| Studio Balanced | Warm natural | studio_punch(80%) + warm_shift(30%) + sat_boost(50%) + black_crush(15%) |
| Studio Dance | Warm cinematic | studio_punch(100%) + warm_shift(40%) + sat_boost(60%) + black_crush(25%) |
| Studio Ambient | No fill light | studio_punch(80%) + warm_shift(100%) + sat_boost(100%) + black_crush(20%) |
| Studio Gold | Warm cinematic | cinema_dark(80%) + golden_warm(75%) + sat_boost(100%) + black_crush(10%) |
| Studio Film | Moody cinematic | film_contrast(60%) + warm_shift(20%) + sat_reduce(30%) + black_crush(40%) |
### Baking Chain LUTs
`generate_chain_lut.rb` bakes multiple presets at different strengths into a single .cube file. This lets you apply a creative preset as one node in Resolve instead of multiple.
```bash
# Bake Studio Balanced into a single LUT
ruby generate_chain_lut.rb correction_luts/studio_balanced_baked.cube \
studio_punch@0.8 warm_shift@0.3 sat_boost@0.5 black_crush@0.15
# Bake Studio Dance
ruby generate_chain_lut.rb correction_luts/studio_dance_baked.cube \
studio_punch@1.0 warm_shift@0.4 sat_boost@0.6 black_crush@0.25
Pre-baked LUTs for all creative presets are committed in correction_luts/.
You can also bake a conversion LUT + creative chain into a single .cube for one-node grading in Resolve:
# Bake conversion + creative into a single pass LUT
ruby generate_chain_lut.rb final_grade.cube \
--conversion=luts/SLog3_to_Rec709.cube \
cinema_dark@0.8 golden_warm@1.0 sat_boost@1.0 black_crush@0.1
Video Export Workflow
Apply conversion + correction LUTs and encode to H.265 in one pass using ffmpeg.
# Extract a sample frame for analysis
ffmpeg -y -ss 19 -i input.mp4 -vframes 1 -vf "scale=1280:-1" -update 1 frame_raw.png
# Apply conversion LUT to frame for preview
ffmpeg -y -i frame_raw.png -vf "lut3d='conversion.cube':interp=tetrahedral" -update 1 frame_709.png
# Full encode: conversion + correction → H.265 4K
# 50Mbps masters (for re-editing):
ffmpeg -i input.mp4 \
-vf "lut3d='conversion.cube':interp=tetrahedral,lut3d='correction.cube':interp=tetrahedral,format=nv12" \
-c:v hevc_videotoolbox -b:v 50M -spatial_aq 1 \
-c:a aac -b:a 192k -tag:v hvc1 output_master.mp4
# 15Mbps web-optimized (for Instagram/web):
ffmpeg -i input.mp4 \
-vf "lut3d='conversion.cube':interp=tetrahedral,lut3d='correction.cube':interp=tetrahedral,format=nv12" \
-c:v hevc_videotoolbox -b:v 15M -spatial_aq 1 \
-c:a aac -b:a 128k -tag:v hvc1 output_web.mp4
Notes:
hevc_videotoolboxuses Apple Silicon hardware encoding (M1/M2/M3)format=nv12converts to YUV420p for compatibility-tag:v hvc1ensures QuickTime/browser playback compatibilityspatial_aq 1enables adaptive quantization for better quality
Conversion LUTs (not in repo)
Conversion LUTs (e.g. Sony S-Log3 → Rec.709, ARRI LogC → Rec.709) are camera-specific and often commercially licensed. Store them in luts/ (gitignored).
Phantom LUTs (phantomluts.com) — ARRI Alexa709 emulation for Sony cameras:
- Location:
luts/a7s3-arri-g8/A7s3 Phntm Arri LUTs G8/65x/SLog3/Neutral A7s3_65x.cube - Variants: Neutral, IceBlue, Jamaica, Tungsten, Utopia (Standard + Legacy versions)
- Use 65x for post, 33x for in-camera/monitoring
- Designed for S-Log3 + S-Gamut3.Cine; enable Cine comp toggle for S-Gamut3 footage
Resolve settings: Colour Science = DaVinci YRGB, Timeline = Rec.709-A (Mac), 3D LUT interpolation = Tetrahedral
Node Order (DaVinci Resolve)
Professional serial node chain:
- Conversion LUT (camera log → Rec.709)
- Contrast / Exposure
- White Balance / Color Temperature
- Skin Tone Correction
- Color Saturation
- Black Levels
- (Noise Reduction — not achievable via LUT)
- (Vignette — not achievable via LUT)
- (Sharpening — not achievable via LUT)
Applying LUTs
DaVinci Resolve: Add a serial node per LUT. Right-click node → LUT → browse to .cube file.
Adobe Premiere Pro: Lumetri Color → Creative → Look dropdown → browse to .cube file.
ffmpeg (batch/preview):
ffmpeg -i input.mp4 -vf "lut3d='conversion.cube':interp=tetrahedral,lut3d='correction.cube':interp=tetrahedral" output.mp4
Color Science Notes
- Desaturating warm tones in HSL produces brown/sepia. Use hue shifting or RGB rebalancing instead.
- Skin tones occupy H=10-35, S=0.08-0.45, L=0.25-0.75. Use all three windows to isolate from light sources.
- S-Gamut3 vs S-Gamut3.Cine: S-Gamut3 is wider. LUTs calibrated for .Cine may oversaturate S-Gamut3 footage. Use
sgamut3_to_cinecompensation. - 3D LUTs allow cross-channel operations — R output can depend on G and B input.
- LUTs have no spatial awareness — no noise reduction, sharpening, or vignettes.
Requirements
- Ruby 2.7+
- Python 3 with Pillow + NumPy (for autograde.py, matchgrade.py, and analyze_frame.rb)
- ffmpeg / ffprobe (for frame extraction and metadata)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: isaacrowntree
- Source: isaacrowntree/color-grade-ai
- License: MIT
- Homepage: https://isaacrowntree.github.io/color-grade-ai/
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.