Commit Graph
23 Commits
Author SHA1 Message Date
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