Nodes/Skoogeer-Noise/Latent Channel Linear Transform
ComfyUI Node

Latent Channel Linear Transform

Glitch, Rotate, and Rearrange Features

By ttulttul·Created 9 months ago·Updated 3 months ago· 14
Latent Channel Linear Transform
  • latent
  • mask
  • latent
operation
seed0
sign_flip_prob0.50
tile_size0
block_size0
alpha0.50
selection_modeall
selection_fraction1.00
selection_count0
selection_orderhighest
selection_indices
mix1.00
match_statsfalse

A latent isn't a picture, it's a stack of feature maps - and most people never touch the individual channels. Latent Channel Linear Transform lets you operate on that channel dimension directly, mixing, permuting, and rotating the features before the VAE decodes them. The results range from subtle material shifts to full-blown codec glitch, all with one seed. If you've ever wanted to break a perfectly good render on purpose, this is the node.

It's one of the four operation modes on a single socket, and each one is a different kind of damage:

  • signed_permute - reorders channels and optionally flips their signs. Crunchy, codec-like glitches that keep the overall structure recognizable.
  • orthogonal_rotate - mixes all channels with an energy-preserving rotation. The README calls this the one that gives smooth "style drift" in material and texture without tearing. This is usually the sweet spot: interesting but not broken.
  • householder_reflect - reflects along one random feature direction. Can feel like a latent "photonegative" or specular inversion.
  • low_rank_shear - measures along one direction, adds along another. Creates blooming or melting effects.

The reason the pack bothers with four modes instead of one "scramble" button is that permutation and rotation are mathematically very different. A permutation just reorders which channel is where; a rotation actually mixes energy across channels. Same seed, wildly different art direction.

What you actually set, beyond the mode:

  • seed - drives which channels get picked and how they transform.
  • selection_mode and friends - all hits every channel; random picks a seeded subset; top_variance and top_roughness pick the channels that carry the most activity or texture (with selection_order choosing highest or lowest). indices lets you type an explicit comma-separated list into selection_indices.
  • mix - your safety dial, 0 to 1. Crank it down and the transform blends with the original. This is the difference between "let me try a thing" and "I regret everything."
  • match_stats - after the transform, re-normalize each channel's mean and standard deviation back to what it was. This keeps the edit from wrecking the latent's statistical profile, which matters if you're feeding the result back into a sampler.

There's also tile_size (per-tile permutations for localized glitches) and block_size (channels per orthogonal block) for the fiddly end of the parameter space. Skip them until you know what you're doing. Output is a single LATENT - decode it to see the damage.

Where it fits

The obvious use is aesthetic: rotate a channel mix, decode, and get a texture/color shift you can blend over a base render in img2img. It's also legitimately useful for data augmentation if you train LoRAs, and for stress-testing what a checkpoint actually encodes. Pair it with LatentChannelStatsPreview so you can see how the channel means and stds move as you drag mix - the two nodes are clearly designed to go together, and the README's own quick-start chains a rotation into the pack's swirl-noise node before decode.

Installing

This is part of the Skoogeer-Noise pack by ttulttul. One install, whole pack:

cd ComfyUI/custom_nodes
git clone https://github.com/ttulttul/Skoogeer-Noise

Restart, or grab it via ComfyUI Manager (search "Skoogeer-Noise"). Dependencies are torch, numpy>=1.26, einops, pyyaml - all usually present. No model downloads, no weights, nothing to fetch.

Gotchas

The classic beginner trap is leaving mix at 1.0, running signed_permute on everything, and getting a mess - dial mix down to 0.3–0.6 first and let the node's mask input localize the effect if you only want part of the image touched. Also, match_stats is on by default in some workflows you'll find online but off here; turn it on if your decoded output is shifting wildly in color. One honest caveat: on Flux.2's patchified 128-channel latents, channel ops hit the 2x2 patch blocks rather than true spatial neighborhoods, so unwrap with the pack's Unpatchify Flux.2 Latent first and re-patchify after.

Categorylatent/channel

Inputs (15)

NameTypeDefaultDescription
latentLATENTLatent to transform in channel-space.
operationCOMBOLinear channel-space transform to apply.
seedINT00–18446744073709550000Seed for deterministic channel selection and random transforms.
sign_flip_probFLOAT0.500–1Probability of flipping channel signs when using signed_permute.
tile_sizeINT00–512When >0 and operation is signed_permute, apply a new permutation per tile (latent pixels).
block_sizeINT00–4096Channels per orthogonal block. 0 means full rotation.
alphaFLOAT0.50-4–4Shear strength for low_rank_shear.
selection_modeCOMBOallHow to choose which channels are transformed.
selection_fractionFLOAT1.000–1Fraction of channels to select when selection_count is 0.
selection_countINT00–4096Exact number of channels to select (overrides selection_fraction when >0).
selection_orderCOMBOhighestWhether to pick high or low variance/roughness channels.
selection_indicesSTRINGComma-separated channel indices to select when selection_mode=indices.
mixFLOAT1.000–1Blend factor for the transformed channels (0=off, 1=full).
match_statsBOOLEANfalseMatch per-channel mean/std after the transform (stabilizes latent stats).
maskoptMASKOptional mask to limit the transform to masked areas.

Outputs (1)

NameTypeDescription
latentLATENT