Commit Graph
25 Commits
Author SHA1 Message Date
facok 6cd650596d Extract shared _chromatic_plane_basis helper and _ANCHOR_HUES constant
Deduplicate the Gram-Schmidt basis construction that was copy-pasted
in decode_lcs_to_hsl, encode_hsl_to_lcs, and calibration.py. Extract
anchor hue values into a module-level constant to prevent silent
divergence. Also remove unnecessary tensor clone in _angle_to_hue and
use torch.empty instead of torch.zeros where all elements are overwritten.
2026-03-17 13:05:27 +08:00
facok 02585b6bf1 Fix bicone HSL mapping by projecting anchors onto chromatic plane
Replace _hue_to_polygon_point with _hue_to_chroma_vector to fix
Type II and interpolated color intervention modes. The old function
interpolated raw 3D anchor positions (mixing lightness into chroma
directions) and ignored calibrated anchor angles. The new function
projects anchors onto the plane perpendicular to the achromatic axis
to get pure chroma radii, then interpolates radius and angle in the
same segment structure as _angle_to_hue for round-trip consistency.
2026-03-17 12:25:49 +08:00
facok 894fb65ef3 Strengthen Warm and Cool preset effects 2026-03-17 07:39:09 +08:00
facok 6fa541ea5a Update README_zh.md 2026-03-17 07:28:29 +08:00
facok 87b78c2f48 Update README.md 2026-03-17 07:27:42 +08:00
facok c0449e3382 Fix BFloat16 error in VAE fingerprinting by casting to float32 2026-03-17 06:57:34 +08:00
facok 773d2bd230 Clarify LCS vs traditional post-processing comparison headings 2026-03-17 06:56:35 +08:00
facok 49b3b4ae44 Polish READMEs: reorganize sections, fix clone URL, tighten wording 2026-03-17 06:45:01 +08:00
facok 750c6484a4 Update READMEs: citation, official repo link, acknowledgments, unofficial notice 2026-03-17 06:39:59 +08:00
facok 20044a9a16 Add LCS vs post-processing comparison to READMEs 2026-03-17 06:32:42 +08:00
facok 48d5f7efb6 Merge LCSCalibrate into LCSLoadData with per-VAE auto-caching
Replace two calibration nodes with a single smart LCSLoadData that
fingerprints VAE weights (sha256 of first decoder weight) and
auto-manages cached calibration files as data/lcs_{fingerprint}.safetensors.
2026-03-17 06:27:55 +08:00
facok 707e789f02 Add server-side preset fallback for headless/batch execution
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.
2026-03-17 05:50:59 +08:00
facok 98bd528bb4 Add README in English and Chinese 2026-03-17 05:44:36 +08:00
facok e8f37b36d1 Add Base preset to reset all tone sliders to defaults 2026-03-17 05:25:54 +08:00
facok 7aa68375f9 Fix color temperature having no visible effect
The warm_dir was a unit vector (norm=1) but LCS chroma vectors have
norms ~40-46, so color_temperature=0.5 only shifted chroma by 1.2%.
Scale warm_dir by mean anchor chroma magnitude so the shift is
proportional. Slider range narrowed from ±2.0 to ±1.0 and preset
values adjusted accordingly (Warm=0.15, Cool=-0.15, Cinematic=0.05).
2026-03-17 05:05:21 +08:00
facok 78be03db46 Add frontend preset sync for LCSToneAdjust sliders
Selecting a preset now updates slider values in real-time via a
frontend JS extension, and users can tweak values after selecting.
Sliders are always visible (removed optional=True). Preset values
live only in JS (single source of truth); Python keeps just the
name list for the combo widget. Sync only fires on explicit user
dropdown interaction, preserving saved slider tweaks on workflow load.
2026-03-17 04:47:57 +08:00
facok 51becf21e4 Use epsilon comparison for tone no-op check and precompute warm_dir
Float equality (!=) can fail after JS→JSON→Python round-trips on
slider values. Switch to epsilon-based _is_default_tone() helper.
Also precompute the warm/cool direction vector once at closure-build
time instead of recomputing it on every denoising step.
2026-03-17 03:47:44 +08:00
facok 56699625e0 Rename LCSContrastAdjust to LCSToneAdjust and add tone presets
The node now controls contrast, brightness, saturation, and color
temperature — "Contrast Adjust" was misleading. Adds 9 one-click
tonal presets (Cinematic, HDR, Vivid, Dramatic, Low Key, High Key,
Warm, Cool, Desaturated) plus Custom mode for manual slider control.
2026-03-17 03:43:10 +08:00
facok 01f5bd308c Add color temperature control to LCSContrastAdjust node
Shifts chroma along the warm (Red+Yellow) ↔ cool (Blue+Cyan) axis
via additive offset before saturation scaling, so saturation=0 still
yields grayscale. Warm direction is derived from chromatic projections
of the 6 hue anchors (stripping their lightness component).
2026-03-17 03:30:30 +08:00
facok ef69e2f9e7 Remove incorrect clamp on LCS lightness in contrast hook
l_scalar (lightness projection onto achromatic axis) can naturally
extend beyond [0,1] during denoising. Clamping destroys highlight/shadow
detail — directly contradicting the purpose of contrast adjustment.
Type I color intervention already operates without clamping LCS coords.
The no-op skip in execute() ensures default params have zero effect.
2026-03-17 03:25:03 +08:00
facok 29dc6379f9 Skip contrast hook when all parameters are at defaults
Avoids clamp and float round-trip artifacts that caused visible
changes even with contrast=1.0, brightness=0.0, saturation=1.0.
2026-03-17 03:09:14 +08:00
facok 600252d5d4 Fix non-contiguous tensor error when saving calibration data
PCA basis from torch.linalg.eigh produces non-contiguous tensors,
which safetensors rejects. Add .contiguous() to all tensors at save time.
2026-03-17 02:55:11 +08:00
facok b4e8dbd3d7 Add LCSContrastAdjust node for contrast, brightness, and saturation control
Operates directly in 3D LCS space by decomposing patches into lightness
(projection onto black→white achromatic axis) and chroma (perpendicular
residual). No HSL round-trip needed, making it faster than the color
intervention path.
2026-03-17 02:49:40 +08:00
facok 0973fd0fd8 Add docstrings to all public functions, classes, and methods
Coverage: 29% → 100% (41/41 public items documented).
Keeps the existing concise style with inline shape annotations.
2026-03-17 02:26:21 +08:00
facok 534bc19033 Implement LCS plugin for training-free color control in FLUX
Implements "The Latent Color Subspace" (arXiv:2603.12261v1, ICML 2026)
as a ComfyUI plugin with V3 API + V2 backward compatibility.

6 nodes across 3 categories:
- LCS/calibration: LCSCalibrate (PCA from VAE), LCSLoadData (cache load)
- LCS/intervention: LCSColorIntervene (single color), LCSColorBatch (multi)
- LCS/observe: LCSPreviewColors (latent color map), LCSStepObserver

Core modules: patchify (16ch->64d patches), bicone HSL<->LCS mapping,
alpha_t/beta_t tables (51 entries from Appendix F), PCA calibration,
and timestep normalization with residual preservation.
2026-03-17 01:43:26 +08:00