Skip to content
Automation
Skill

/color-correction

Diagnose and fix video/image color OBJECTIVELY with the get_image (action:"analyze_color") tool (scopes/stats such as black/white points, contrast, saturation, clipping, cast) instead of eyeballing a contact sheet. Covers the "washed out" signature, why reference color-match

From plugin
comfyui-mcp
88442 skills4 agents11 commands1 MCP

Claude Code

$ npx -y skills add artokun/comfyui-mcp --skill color-correction --agent claude-code

SKILL.md

color-correction.SKILL.md
name: color-correction
description: Diagnose and fix video/image color OBJECTIVELY with the get_image (action:"analyze_color") tool (scopes/stats such as black/white points, contrast, saturation, clipping, cast) instead of eyeballing a contact sheet. Covers the "washed out" signature, why reference color-match (mkl/ColorMatch/ColorMatchAdobe) CAN'T add contrast a flat source lacks, the levels/contrast-stretch fix (core AdjustContrast / CurveEditor), the measure→fix→re-measure loop, the side-by-side sandbox pattern, and where to place the fix in a render graph (after decode, before save). Use when a render looks washed out / flat / dull / over-saturated / color-cast, or when deciding between a color-match and a contrast/levels fix.
globs:
  - "**/*.json"
  - "**/packs/**"

Color Correction (measure, don't eyeball)

The core principle

You cannot reliably judge color from a storyboard or contact sheet. "Is it washed out?" flip-flops by eye, especially on AI-gen video. Make color measurable with the `get_image (action:"analyze_color")` MCP tool, read the numbers like a colorist reads scopes, pick the fix the data points to, then re-measure to confirm. The whole skill is this loop:

extract a frame ─► get_image (action:"analyze_color") ─► read black/white points + contrast + saturation
       ▲                                          │
       │                                          ▼
   re-measure  ◄──── apply fix (levels / contrast / match) ◄── diagnose from the numbers

> Origin: on a WAN-Animate render we argued for many turns over whether the clip was > "washed out." The instant we measured it, the answer was unambiguous and the *correct* > fix (a contrast stretch, not the color-match nodes we'd been adding) fell straight out.

---

The `get_image (action:"analyze_color")` tool

Read-only. Source = `asset_id`, a ComfyUI output ref (`filename`/`subfolder`/`type`), or an image `path` (absolute, or under the output dir). It returns per-image stats, heuristic flags, a one-line verdict, and optionally an overlaid R/G/B/luma histogram PNG.

get_image({ action: "analyze_color", filename: "render_00007_.png" })       # absolute numbers
get_image({ action: "analyze_color", path: "frame.png", reference_path: "src.jpg" })  # + shot-match deltas
get_image({ action: "analyze_color", filename: "x.png", histogram: true })  # + histogram image

For videos, `get_image (action:"analyze_color")` is image-only (no ffmpeg dep). Extract a frame first with the ComfyUI venv's cv2:

"<comfy-venv>/python" -c "import cv2; c=cv2.VideoCapture(r'IN.mp4'); n=int(c.get(7)); \
  c.set(1, n//2); _,f=c.read(); cv2.imwrite(r'frame.png', f)"

Grab the middle frame, or frame 0. For window-drift checks grab a frame from each window.

What the numbers mean (8-bit)

| Field | Reads like a scope | Healthy-ish | |---|---|---| | `luma.blackPoint` (1st pct) | where shadows bottom out | ~0–16 (lifted if >16) | | `luma.whitePoint` (99th pct) | where highlights top out | ~240–255 (dim if <235) | | `luma.contrast` (std) | overall punch | ~45+ (flat if <45) | | `luma.dynamicRange` | white−black | wide is good | | `saturation.meanSaturation` (HSV S) | vectorscope spread | ~0.25+ (dull if <0.22) | | `channels.{r,g,b}Mean` + `castHint` | RGB parade / white balance | spread <~12 = neutral | | `luma.clippedHighPct/LowPct` | blown / crushed pixels | keep low (<~2%) |

Flags: `washedOut, lowContrast, liftedBlacks, dimHighlights, lowSaturation, colorCast`.

---

The "washed out" signature

Washed out means compressed tonal range, and it has an exact fingerprint:

  • `whitePoint` well below 255 (e.g. 191), so highlights never reach white
  • `blackPoint` lifted off 0 (e.g. 45), giving milky shadows
  • `contrast` low (std < 45)
  • often *normal* saturation. Washout is usually not a saturation problem.

If you see that, the fix is a levels / contrast stretch, not a color match. In a real case, a WAN-Animate frame measured blackPoint 45 / whitePoint 191 / contrast 43, clearly a range problem; saturation 0.25 was fine.

---

The load-bearing insight: a reference-match can't add contrast the source lacks

The instinct is to "match the render to the input photo" with a color-match node (`ColorMatchV2` mkl/hm, `ImageColorMatchAdobe+`, easy `imageColorMatch`). Measure the reference first. If the reference is itself flat (e.g. a casual phone selfie with blackPoint 40, contrast 44), matching to it cannot produce punch; you'll match your way to the *same* flat numbers. In the real case, mkl and Adobe matches both left the frame flagged `washedOut` (whitePoint only crept from 191 to ~218).

So:

  • Use a reference-match (`ColorMatchV2`, `ImageColorMatchAdobe+`) when you want to *match

a known-good graded frame or shot-match across clips*, and the reference is actually good.

  • Use a levels / contrast stretch when the defect is compressed range (the washout case).

It targets full range *regardless* of the reference. This is usually the real fix.

---

The fix: contrast / levels stretch (core nodes, no install)

`AdjustContrast` (core `comfy_extras.nodes_dataset`, category *image/adjustments*) has one `factor` (1.0 = none, >1 = more). It pivots around mid-gray, so it pushes the white point up and the black point down together. Tune it by measurement, not feel. A real measured sweep on the washout frame:

| factor | blackPoint | whitePoint | contrast | sat | clippedHigh | verdict | |---|---|---|---|---|---|---| | 1.3 | 29 | 239 | 56 | 0.33 | **0%** | ✅ not washed (slightly soft) | | ~1.4 | ~20 | ~247 | ~60 | ~0.38 | ~1–2% | ✅ **sweet spot** | | 1.6 | 7 | 254 | 67 | 0.44 | **7.2%** ⚠️ | punchy but blows highlights |

Pick the factor that lands whitePoint ~248 to 255 with `clippedHighPct` < ~2%. Going too far (1.6 here) blows highlights *and* over-warms, because per-channel contrast drops blue more than red and `castHint` worsens. The sweet spot was ~1.4.

Other levers when contrast alone isn't enough: -

Read more
@artokun
Ships withcomfyui-mcp

<img src="docs/images/demo-poster.jpg" width="760" alt="The Agent panel driving ComfyUI end to end. Click to watch the demo"> The Agent panel driving ComfyUI end to end. It reads what is installed locally, wires the graph, frees VRAM, and runs the render.

88442 skills4 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
884
Star history of artokun/comfyui-mcp on GitHub, a chart by star-history.com

Other skills on comfyui-mcp.

ai-toolkit-trainer

ai-toolkit-trainer

Train custom LoRAs with ostris AI-Toolkit. Covers WAN 2.2/2.1 (people, styles, video motion) and Z-Image (Turbo & Base, low-VRAM…

@artokun@artokunInstall Skill
anima-base

anima-base

Anime/illustration text-to-image (ANIMA 1.0, ~2B Cosmos DiT). Use for anime, manga, illustrated characters; accepts Danbooru tags…

@artokun@artokunInstall Skill
anima-lora-trainer

anima-lora-trainer

Train a custom anime LoRA on the ANIMA base model with Citron's local Gradio trainer (kohya sd-scripts), <6GB VRAM,…

@artokun@artokunInstall Skill
civitai

civitai

Discover Civitai models with the BUILT-IN download_model action:"search_civitai" and install/generate them locally. Find a…

@artokun@artokunInstall Skill
comfyui-core

comfyui-core

Core ComfyUI knowledge covering workflow format, node types, pipeline patterns, and MCP tool usage

@artokun@artokunInstall Skill

More skills from other plugins.

agent-builder

agent-builder

Load immediately after an Agent intent, before the first agent_builder_* call. Governs how you create, configure, test, and…

n8n2w209k
@n8n-io@n8n-ioInstall Skill
browser-use

browser-use

Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…

@browser-use@browser-useInstall Skill
agent-browser

agent-browser

Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…

@vercel-labs-2@vercel-labs-2Install Skill
add-anydoc

add-anydoc

Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when…

@nanocoai@nanocoaiInstall Skill

Questions about color-correction.

Which coding agents can use color-correction?
color-correction installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.