From image-production
Use when the user wants to automatically correct the white balance of an image (or batch) — neutralise colour casts from indoor lighting, mixed light, underwater shots, scans, or uncalibrated cameras. Implements gray-world (default), white-patch (per-channel auto-level), and a combined mode via ImageMagick. Operates on JPEG/PNG/TIFF/WebP; for RAW use `darktable-cli` instead.
npx claudepluginhub danielrosehill/claude-code-plugins --plugin image-productionThis skill uses the workspace's default tool permissions.
Neutralise colour casts without per-image manual correction. Three algorithms, one CLI.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Neutralise colour casts without per-image manual correction. Three algorithms, one CLI.
-auto-level stretches each channel to full range. Strong correction; fails on scenes lacking a true white reference.Do not use this skill when:
darktable-cli with --apply-custom-presets and the temperature module set to as shot to reference. White-balancing a baked JPEG throws away headroom that's still in the RAW.gray-world (default) | white-patch | combined.--recursive for directory descent._wb next to the source. --output-dir <path> to write into a sibling folder. --overwrite to replace.0.0 to 1.0 (default 1.0). Blends the corrected image with the original via -compose blend -define compose:args=<pct>. Use 0.5 for a softer touch.on. After channel scaling, rescale so the mean luminance matches the original (prevents brightness drift). --no-preserve-luma to disable.Verify ImageMagick 7+. magick -version | head -1. Fall back to convert (IM6) if magick is missing — the syntax below works on both with the leading binary swapped. If neither, point at install-deps.
Enumerate inputs. Accept JPEG/JPG/PNG/TIFF/TIF/WebP. Skip and note RAW formats.
gray-world:
magick "$IN" \
-colorspace sRGB \
-channel R -evaluate multiply $(magick "$IN" -colorspace sRGB -format "%[fx:mean/mean.r]" info:) \
-channel G -evaluate multiply $(magick "$IN" -colorspace sRGB -format "%[fx:mean/mean.g]" info:) \
-channel B -evaluate multiply $(magick "$IN" -colorspace sRGB -format "%[fx:mean/mean.b]" info:) \
+channel "$OUT"
Each fx:mean/mean.<c> is the gain that drives that channel's mean to the global mean. Three info: calls is wasteful for batch — cache via a single magick identify -format "%[fx:mean] %[fx:mean.r] %[fx:mean.g] %[fx:mean.b]" "$IN" and compute gains in shell.
white-patch:
magick "$IN" -channel RGB -auto-level +channel "$OUT"
Independent per-channel histogram stretch to [0,1]. Aggressive; clips highlights if any channel already saturates.
combined:
Run gray-world to a temp file, then:
magick "$TMP" \( +clone -channel RGB -auto-level +channel \) \
-compose blend -define compose:args=50 -composite "$OUT"
Preserve luminance (when enabled): after step 3/4/5, measure luminance before and after and rescale:
L_IN=$(magick "$IN" -colorspace Gray -format "%[fx:mean]" info:)
L_OUT=$(magick "$WB" -colorspace Gray -format "%[fx:mean]" info:)
GAIN=$(awk "BEGIN{print $L_IN/$L_OUT}")
magick "$WB" -evaluate multiply "$GAIN" "$OUT"
Strength blend (when <1.0):
magick "$IN" "$WB" -compose blend -define compose:args=$(awk "BEGIN{print $STRENGTH*100}") -composite "$OUT"
For batch, parallelise with xargs -P $(nproc) over the file list. Skip files that already end in _wb to avoid recursive re-processing.
white-patch is more honest, or skip auto-WB entirely and use a colour picker on a known-neutral patch.combined at --strength 0.7 — strong enough to neutralise obvious casts, weak enough to preserve scene character.-profile sRGB.icc explicitly if the pipeline downstream is profile-strict.apply-filters may call it as one step; this skill exists to do WB-only work without the rest of the pipeline.