Frontend JS syncs preset values into sliders on user interaction, but headless runners (e.g. Lumi-Batcher) skip the frontend entirely. When a preset is selected but all sliders are still at defaults, execute() now applies the preset values server-side as a fallback.
ComfyUI-LCS
Training-free color control for FLUX via the Latent Color Subspace.
Based on the paper "The Latent Color Subspace" (ICML 2026), which discovers that color in FLUX's 64-dimensional latent patch space lives in a 3D subspace (found via PCA with 100% color variance). The remaining 61 dimensions encode structure and detail, orthogonal to color.
This plugin manipulates colors directly in the 3D LCS during diffusion sampling — no model training, no LoRA, no post-processing.
Features
- Color Steering — Push generated image colors toward any target color
- Batch Multi-Color — Apply different colors to each image in a batch
- Tone Adjustment — Contrast, brightness, saturation, color temperature with one-click presets
- Localized Control — Optional mask input for region-specific color changes
- Latent Color Preview — Visualize color structure without VAE decoding
- Step Observer — Save per-step color previews to inspect the diffusion process
Installation
Clone into your ComfyUI custom nodes directory:
cd ComfyUI/custom_nodes
git clone https://github.com/YOUR_USERNAME/ComfyUI-LCS.git
Install dependencies (usually already present in ComfyUI):
pip install einops safetensors
Nodes
Calibration
| Node | Description |
|---|---|
| LCS Calibrate | Compute LCS basis and anchors from a FLUX VAE via PCA on solid-color images. Auto-saves to data/lcs_calibration.safetensors. |
| LCS Load Data | Load cached calibration data, or auto-calibrate if a VAE is provided. |
Run calibration once — the result is cached and reused across sessions.
Intervention
| Node | Description |
|---|---|
| LCS Color Intervene | Steer colors toward a target during generation. Supports Type I (LCS shift), Type II (HSL shift), or interpolated mode. |
| LCS Color Batch | Apply different target colors per batch item. Outputs batch_size for connecting to EmptyLatentImage. |
| LCS Tone Adjust | Adjust contrast, brightness, saturation, and color temperature. Includes preset dropdown with real-time slider sync. |
Observation
| Node | Description |
|---|---|
| LCS Preview Colors | Decode latent colors to an RGB preview image without VAE decoding. |
| LCS Step Observer | Save per-step color preview PNGs to ComfyUI's temp directory for debugging. |
Tone Presets
Select a preset from the dropdown — sliders update in real-time. Tweak sliders after selecting a preset for fine-tuning. Select Custom to set values manually without preset interference.
| Preset | Contrast | Brightness | Saturation | Temperature |
|---|---|---|---|---|
| Base | 1.0 | 0.0 | 1.0 | 0.0 |
| Cinematic | 1.20 | -0.05 | 0.90 | 0.05 |
| HDR | 1.40 | 0.0 | 1.20 | 0.0 |
| Vivid | 1.10 | 0.0 | 1.50 | 0.0 |
| Dramatic | 1.50 | -0.10 | 0.85 | 0.0 |
| Low Key | 1.30 | -0.20 | 0.80 | 0.0 |
| High Key | 0.80 | 0.20 | 0.90 | 0.0 |
| Warm | 1.0 | 0.0 | 1.0 | 0.15 |
| Cool | 1.0 | 0.0 | 1.0 | -0.15 |
| Desaturated | 1.0 | 0.0 | 0.40 | 0.0 |
Quick Start
Basic Color Control
LCS Load Data → LCS Color Intervene → KSampler
↑
(pick a color)
- Add LCS Load Data — connect your FLUX VAE (first run only, calibrates automatically)
- Add LCS Color Intervene — connect MODEL and LCS_DATA
- Pick a target color, set strength (default 1.0)
- Connect the output MODEL to your KSampler
Tone Adjustment
LCS Load Data → LCS Tone Adjust → KSampler
↑
(select preset or
adjust sliders)
- Add LCS Load Data → LCS Tone Adjust
- Select a preset (e.g., "Cinematic") or use Custom mode
- Fine-tune sliders as needed
Multi-Color Batch
LCS Load Data → LCS Color Batch → KSampler
↓
batch_size → EmptyLatentImage
Enter comma-separated hex colors (e.g., #FF0000,#00FF00,#0000FF). Each color applies to one batch item.
Intervention Modes
| Mode | Description | Best For |
|---|---|---|
| interpolated (default) | Blends Type I and Type II using sigma as weight | General use |
| type_i | Direct translation in 3D LCS space | Strong global color shifts |
| type_ii | Per-patch HSL interpolation via bicone geometry | Precise local color control |
Key Parameters
- strength (0.0–2.0): Intervention intensity. 1.0 = full, 0.0 = none.
- start_step / end_step: Step range for intervention. Paper optimal: 8–10 of 50 steps.
- mask: Optional. Bilinearly downsampled to patch grid for localized control.
How It Works
- Project: Convert denoised prediction to 64D patch space, project onto 3D LCS basis
- Decompose: Separate the 3D color coordinates from the 61D structural residual
- Normalize: Transform to the reference timestep (t=50) using learned alpha/beta statistics
- Manipulate: Shift colors, adjust tone, or apply other transformations in 3D LCS
- Reconstruct: Denormalize, add back the preserved 61D residual, convert to latent space
The 61D residual (structure, texture, detail) is never modified — only the 3D color subspace is touched.
File Structure
ComfyUI-LCS/
├── __init__.py # Entry point (V3 + V2 compat)
├── requirements.txt
├── core/
│ ├── calibration.py # PCA calibration pipeline
│ ├── color_space.py # Bicone LCS ↔ HSL mapping
│ ├── defaults.py # Alpha/beta tables from paper
│ ├── lcs_data.py # LCSData dataclass
│ ├── patchify.py # Patch ↔ latent conversion
│ └── timestep.py # Sigma/timestep utilities
├── nodes/
│ ├── calibrate.py # LCSCalibrate, LCSLoadData
│ ├── intervene.py # LCSColorIntervene, LCSColorBatch, LCSToneAdjust
│ └── observe.py # LCSPreviewColors, LCSStepObserver
├── data/ # Cached calibration files
└── web/js/
└── tone_preset.js # Frontend preset sync
Citation
@inproceedings{lcs2026,
title={The Latent Color Subspace},
author={...},
booktitle={ICML},
year={2026},
note={arXiv:2603.12261v1}
}
License
MIT