Extensions/comfyui-colorfix-v3
ComfyUI Extension

comfyui-colorfix-v3

ComfyUI custom node implementing the tile_colorfix color correction algorithm from A1111's ControlNet extension, supporting both SD/SDXL and Flux models. (Description by CC)

By ihorpankin·Created 8 months ago·Updated 5 days ago· 6
ihorpankin/comfyui-colorfix-v3
Nodes10
On cloudLocal install
Categorycolorfix-v3, colorfix-v3/flux
Stars6
Updated5 days ago
Readme

comfyui-colorfix-v3

ComfyUI custom node extension implementing the tile_colorfix algorithm from A1111's ControlNet extension. Supports both SD/SDXL and Flux models (Dev, Schnell, Klein and other Flux variants).


Examples

| Reference | SDXL + ColorFix + ControlNet Tile | Flux + ColorFix + ControlNet + LoRA | |:---------:|:---------------------------------:|:-----------------------------------:| | Reference | SDXL Result | Flux Result | | Input reference image | txt2img XL + ColorFix + ControlNet + Tile | txt2img Flux + ColorFix + ControlNet + LoRA |

ColorFix Effect Comparison

| SDXL: With vs Without ColorFix | Flux: With vs Without ColorFix | |:------------------------------:|:------------------------------:| | XL ColorFix comparison | Flux ColorFix comparison |

ControlNet Mode Comparison

| SDXL ControlNet Modes | Flux ControlNet Modes | |:---------------------:|:---------------------:| | XL ControlNet modes | Flux ControlNet modes |

Flux Blur Mode & Weight Test

Flux blur mode and weight test

FLUX.3 Klein Tests

blur_k is a trade-off: smaller values transfer color more strongly but also leak the reference's structure; larger values leak less but transfer less color. Four references (painting, anime, two photos), same seed and settings:

| blur_k | Across all four tests | |--------|-----------------------| | 4 | Always leaks the reference's structure — in the photo tests it practically re-draws the reference | | 8 | Strongest color, faint structure traces (tested on 1–2 only) | | 12–16 | Best range for tile mode: full palette and no direct copying, but the pose, framing or layout can still drift toward the reference. Start at 12; if traces of the reference still show, go to 16 | | 24–32 | Color weakens and the composition drifts back toward the no-ColorFix result |

If the reference is a different picture and the model's own composition matters more than exact object colors, use AdaIN mode instead.

Test 1 — painterly portrait

FLUX.3 Klein ColorFix test 1

| Panel | What it is | Result | |-------|------------|--------| | Reference | assets/reference.png, resized to 896×1024 and VAE-encoded into ref_latent | White hair, grey/white palette, red accents, dark corners | | No ColorFix | Plain generation, model goes straight into KSampler | Brown hair, beige fur, light background — the model's own colors | | blur_k = 4 | Model → Flux Tile ColorFix Patcher → KSampler | Too strong: copies the reference's structure (hair over the eyes, smeared face) | | blur_k = 8 | Same | Strong color transfer, some reference structure still shows through | | blur_k = 12 | Same | Best balance in this test: white hair and grey palette, face, pose and hand generated by the model | | blur_k = 16 | Same | No reference structure, but hair turns grey-brown; only fur and background keep the palette | | blur_k = 24 | Same | Like 16, color transfer weaker still | | blur_k = 32 | Same | Brown hair again, close to no ColorFix; palette only in fur and background |

Settings shared by all generations:

| Parameter | Value | |-----------|-------| | Diffusion model | flux3-image-klein-base-bf16.safetensors | | VAE | flux2-vae.safetensors (used for both encoding the reference and decoding) | | Text encoder | qwen3vl_4b_int8_convrot.safetensors, CLIPLoader type flux3 | | Latent | EmptyFlux2LatentImage 896×1024 | | Sampler | KSampler euler / simple, 30 steps, cfg 3.5, seed 42, denoise 1.0 | | ColorFix | weight 1.0, blur_mode: gaussian (smoother); only blur_k changes between panels | | Prompt | Digital painting portrait of a young woman with short bob haircut, wearing a fur coat, one hand raised to her lips, looking at the viewer, loose expressive brush strokes, close-up | | Negative prompt | empty |

The prompt doesn't mention any colors, so every color difference from the "No ColorFix" panel comes from ColorFix. Reproduce with test_workflows/FLUX3_klein_colorfix_test_api.json (API format; put reference.png into ComfyUI's input folder first).

Test 2 — anime full body, flat color areas

FLUX.3 Klein ColorFix test 2

| Panel | Result | |-------|--------| | Reference | Plum trench coat, dark purple hair, pink backdrop with an olive arc, olive floor | | No ColorFix | Beige coat, light hair, white backdrop with a grey circle | | blur_k = 4 | Structure leaks in: the reference's olive arc on the right, a blotch at the shoulder, a ghost hand at the waist | | blur_k = 8 | Strongest color (plum coat, darker hair, pink backdrop, olive floor), the reference arc only faintly visible | | blur_k = 12 | Best balance: full palette and the model's figure, but the backdrop follows the reference's pink-and-olive layout and the circle shrinks to a thin line | | blur_k = 16 | Same palette, coat slightly lighter | | blur_k = 24 | Coat drifts toward brown, backdrop stays pink | | blur_k = 32 | Reddish-brown coat, pink backdrop still there |

Same settings as Test 1 except: 768×1120, reference 418421c125d9448d0d7d4714c9a8780f.jpg, prompt Anime illustration of a young woman with short hair tied back, wearing a long belted trench coat, gloves and ankle boots, walking and looking over her shoulder, full body, plain studio backdrop with a large circle shape, clean cel shading.

Unlike Test 1, color carries over even at blur_k = 32: this reference is made of large flat color areas (backdrop, floor), which live almost entirely in the low frequencies that ColorFix transfers. References with more fine detail lose color faster as blur_k grows.

Reproduce with test_workflows/FLUX3_klein_colorfix_test2_api.json (put the reference image into ComfyUI's input folder under that filename, or change the LoadImage node).

Test 3 — photo, single saturated color

FLUX.3 Klein ColorFix test 3

| Panel | Result | |-------|--------| | Reference | Royal-blue satin gown, dark wet stairs, cold vertical light strips | | No ColorFix | Champagne ruched gown, warm concrete | | blur_k = 4 | Practically re-draws the reference: same pose, light strips and dress cut | | blur_k = 12 | Best: deep blue gown and cold blue corridor, no direct copying, but the tiered dress and back-wall light strips drift toward the reference | | blur_k = 16 | Nearly identical to 12 | | blur_k = 32 | Pale icy-blue gown; the no-ColorFix dress design comes back |

Reference fashion_portrait_blue_silk_gown_vis.png, 896×1152, prompt Fashion editorial photograph of a woman with short cropped hair and visor sunglasses wearing a voluminous ruffled satin ball gown, standing on a staircase in a concrete corridor lit by vertical light strips, full body, dramatic lighting. Workflow: test_workflows/FLUX3_klein_colorfix_test3_api.json.

Test 4 — photo, muted color on a gradient

FLUX.3 Klein ColorFix test 4

| Panel | Result | |-------|--------| | Reference | Teal quarter-zip sweater, grey-blue gradient backdrop | | No ColorFix | Khaki knit sweater, light grey backdrop | | blur_k = 4 | Copies the reference's pose and framing | | blur_k = 12 | Teal sweater and gradient, but a dark patch by the hair — a trace of the reference's hair. The head still turns toward the reference's pose | | blur_k = 16 | Best: same palette, the patch is gone; the pose still follows the reference | | blur_k = 32 | Still teal, but the backdrop turns hazy and the left sleeve blends into it |

Reference portrait_model_denim.png, 896×1152, prompt Studio fashion photograph of a young man with short curly hair wearing a textured quarter-zip sweater with embossed curved seams, side profile, head tilted down, plain gradient studio backdrop, soft directional light. Workflow: test_workflows/FLUX3_klein_colorfix_test4_api.json.

Each test uses a single seed, so treat 12–16 as a starting range, not a fixed rule.

Keeping the Model's Geometry: AdaIN

Tile mode transfers color by position: whatever was in the top left of the reference ends up in the top left of the result. That suits img2img and upscaling, where both share a composition. With an unrelated reference, the composition either follows the reference or the colors land in the wrong places.

transfer_mode: adain (global) on ColorFix Patcher matches each latent channel's overall mean and spread instead, so no position information from the reference is used:

x0_fixed = (x0_prd - mean(x0_prd)) / std(x0_prd) * std(x0_ref) + mean(x0_ref)

Tile vs AdaIN on three references

| Mode | Composition | Color | |------|-------------|-------| | tile, blur_k 12 | Pose, dress or backdrop layout drift toward the reference | Closest to the reference, including object colors: blue gown, plum coat | | adain, from the first step | No reference silhouette or layout, but the image still changes: the gown's design differs from the no-ColorFix result | Overall palette only; gown turns silver-blue, coat brown | | adain, start_percent 0.15 | Closest to the no-ColorFix result of the modes compared; not identical (the anime figure's stride changes) | Recognizable palette, especially the anime backdrop. Object colors still don't follow the reference: the gown stays gold |

Which to use: tile when the reference and the output share a composition or exact object colors matter most; adain with start_percent around 0.15 when the reference is a different picture and the composition matters most; add tile_mix for a middle ground.

AdaIN limitations:

  • It sets the palette of the whole frame, not what color each object gets, so a blue dress in the reference doesn't produce a blue dress. Color can land on the wrong things: the anime figure's legs turn crimson in the AdaIN panels here.
  • weight 0.7 gave mixed results: on the sweater it stayed closer to the no-ColorFix framing than weight 1.0, on the anime reference it mostly muted the color. Adding it to start_percent 0.15 (anime only) changed little. adain mean-only shifts tone without matching contrast, and came out darker on both photo references.
  • These results come from three references and a single seed, so treat them as a starting point.

Full grids: sweater, gown, anime. Workflows: sweater, gown, anime. Prompts and references are the same as in Tests 2–4, with the same sampler settings.

Hybrid: AdaIN + tile (tile_mix)

tile_mix blends a share of tile transfer over the AdaIN result, so the palette comes from AdaIN and some color follows the reference's positions:

x0_fixed = adain + tile_mix * (tile(adain, blur_k) - adain)

AdaIN + tile hybrid on FLUX.3 Klein

Compared with pure AdaIN, the model's pose and scene stay in place while object colors move toward the reference: the gown's skirt turns blue. The cost is faint traces of the reference's layout: part of the sweater goes pale where the reference's backdrop was light, and an olive band from the reference's floor crosses the anime backdrop.

| Setting | Effect | |---------|--------| | transfer_mode: adain, start_percent 0.15, tile_mix 0.5, blur_k 32 | Good starting point on all four models tested. If a light or dark reference backdrop bleeds onto your subject, lower tile_mix or set it to 0 | | Lower blur_k (Klein 16) | Stronger color, more traces of the reference, such as a dark cloud above the sweater | | Lower tile_mix (0.25) | Closer to pure AdaIN, smaller effect |

Color still follows position in the frame, not objects. The gown's blue lands on the skirt because the reference's blue occupies a similar area; where the two layouts differ more, color can land on the wrong thing.

Other models

The same comparison on FLUX.1 Dev, an SDXL fine-tune and Qwen Image. These runs used the now deprecated Flux Tile ColorFix Patcher, plus Tile ColorFix Patcher for the SDXL tile column. ColorFix Patcher reproduced them pixel for pixel at the matching radius in a spot check on each of the four models.

Tile, AdaIN and hybrid on FLUX.1 Dev

Tile, AdaIN and hybrid on Juggernaut XL v9

Tile, AdaIN and hybrid on Qwen Image 2512

| Model | Settings | Result | |-------|----------|--------| | FLUX.1 Dev (flux1-dev-fp8) | euler / simple, 20 steps, cfg 1.0, FluxGuidance 3.5 | Same pattern as Klein. Weaker object color (the gown only reaches slate blue), and pure AdaIN gave bright artifacts on the anime figure: red face and legs. The hybrid fixed the face; the legs stayed red | | Juggernaut XL v9 | dpmpp_2m / karras, 30 steps, cfg 5 | Same pattern. Best gown of the three models: blue dress in nearly the same scene as the no-ColorFix result. adain and the hybrid still change the lighting, and the sweater's face goes cooler with the hybrid | | Qwen Image 2512 (qwen_image_2512_fp8_e4m3fn) | euler / simple, 50 steps, cfg 4, ModelSamplingAuraFlow shift 3.1 | Hybrid gave a blue gown and the closest anime palette, with pose and scene near the no-ColorFix result. On the sweater, pure adain is cleaner: with the hybrid, the left sleeve goes pale where the reference's backdrop was light |

blur_k is measured in latent pixels, so the same value covers a different image area per model. FLUX.1, SDXL and Qwen Image 2512 downscale by 8, Klein by 16: blur_k 24 on these models covers about the same area as blur_k 12 on Klein. The blur_k ceiling of 32 on them matches only 16 on Klein.

blur_radius_px on ColorFix Patcher sets the radius in image pixels instead, and the node converts it using the model's downscale. Values matching the runs above:

| Setting | blur_radius_px | Tested as | |---------|------------------|-----------| | Tile mode | 192 | blur_k 24 on ×8 models, blur_k 12 on Klein | | Hybrid | 256 | blur_k 32 on ×8 models, blur_k 16 on Klein | | Hybrid, softer on Klein | 512 | blur_k 32 on Klein. Out of reach of blur_k on ×8 models and not yet tested there |

The same radius gives comparable coverage, not identical results: each model still responds to the transfer in its own way. Conversion was checked on Klein and Qwen Image 2512, where a matching blur_radius_px reproduced the blur_k result pixel for pixel.

These runs use one seed and three references per model, and Juggernaut is the only SDXL model tested. Base SDXL, anime fine-tunes and SD 1.5 are untested. Workflows (API format):

| Reference | FLUX.3 Klein | FLUX.1 Dev | Juggernaut XL | Qwen Image 2512 | |-----------|--------------|------------|---------------|-----------------| | Sweater | workflow | workflow | workflow | workflow | | Gown | workflow | workflow | workflow | workflow | | Anime | workflow | workflow | workflow | workflow |

Latents with a time axis: Qwen Image uses a latent format with a time axis, so the node treats each frame as its own image. Other models with the same format (Krea 2, JoyImage, Anima, Cosmos Predict2, Ming Image) and video models are untested; for video, only tensor shapes have been checked, not the visual result.

Why not just delay tile mode?

start_percent and blur_k_start also work in tile mode, but on their own they don't solve this. On the sweater reference they kept the model's pose, while the reference's light background and dark figure appeared over it like a double exposure. blur_k 4 with start_percent 0.2 pulled the pose back toward the reference.

Delayed tile mode on the sweater reference

Workflow: test_workflows/FLUX3_klein_colorfix_geometry_api.json.


Nodes

Any image model

| Node | Description | |------|-------------| | ColorFix Patcher | Start here. Tile, AdaIN or hybrid color transfer, with the blur radius set in image pixels so one value carries across models. Run on FLUX.3 Klein, Qwen Image 2512, FLUX.1 Dev and Juggernaut XL v9; other models are untested. |

SD / SDXL

| Node | Description | |------|-------------| | Tile ColorFix Patcher | Patches the model to apply color correction at every denoising step. Transfers low-frequency color from a reference image while preserving AI-generated detail. | | Tile ColorFix+Sharp Patcher | Same as above with additional detail enhancement via CFG sharpening. | | Apply Ultimate ControlNet | Apply ControlNet with A1111-compatible control modes (balanced / prompt / control). | | Ultimate Multi-ControlNet Stack | Build a stack of up to 3 ControlNets with per-slot on/off, strength, start/end percent, and control mode. | | Apply Ultimate Multi-ControlNet | Apply a multi-ControlNet stack to conditioning (SD/SDXL). |

Flux (Dev / Schnell / Klein)

| Node | Description | |------|-------------| | Flux Tile ColorFix Patcher | Deprecated, use ColorFix Patcher. Saved workflows keep working. | | Flux Tile ColorFix+Sharp Patcher | Deprecated, use ColorFix Patcher in tile mode with sharpness. Saved workflows keep working. | | Apply Ultimate ControlNet (FLUX) | Apply single ControlNet with Flux-adapted control modes. | | Apply Ultimate Multi-ControlNet (FLUX) | Apply a multi-ControlNet stack to conditioning (Flux). |

Note: The Flux nodes work with FLUX.1 (Dev, Schnell) and FLUX.3 Klein. The algorithm operates on latent tensors via ComfyUI's model patching API and does not depend on the channel count, so any Flux-based model that runs through KSampler is supported.

FLUX.3 Klein uses the Flux2 latent format (128 channels, 16× spatial downscale vs 8× for FLUX.1). In tile mode, use blur_k 12–16 (start at 12, raise to 16 if the reference's shapes still show through): lower values (4–8) pass the reference's structure along with its colors, 24+ transfers less color. See the FLUX.3 Klein tests above.


Example Workflows

Ready-to-load workflows with ColorFix Patcher are in example_workflows/. They also appear in ComfyUI's template browser under this extension. Put reference.png from assets/ in ComfyUI's input folder, or load your own image.

| Workflow | Use it for | |----------|------------| | ColorFix_FLUX3_Klein | FLUX.3 Klein, unrelated reference | | ColorFix_img2img_tile_FLUX3_Klein | img2img, reference and output share a composition | | ColorFix_Qwen_Image_2512 | Qwen Image 2512, unrelated reference | | ColorFix_FLUX1_Dev | FLUX.1 Dev, unrelated reference | | ColorFix_SDXL | SDXL (Juggernaut XL v9), unrelated reference |

Results from the example workflows

Best settings found per model for an unrelated reference, with transfer_mode: adain and start_percent 0.15. Each workflow's note lists them too.

| Model | Sampler | tile_mix | blur_radius_px | Notes | |-------|---------|------------|------------------|-------| | FLUX.3 Klein | euler / simple, 30 steps, cfg 3.5 | 0.5 | 512 | 256 gives more object color and more traces of the reference | | Qwen Image 2512 | euler / simple, 50 steps, cfg 4, shift 3.1 | 0.5 | 256 | If a light backdrop in the reference pales your subject, use tile_mix 0 | | FLUX.1 Dev | euler / simple, 20 steps, cfg 1.0, FluxGuidance 3.5 | 0.5 | 256 | Keep tile_mix above 0: pure AdaIN gave a red face on the anime test | | Juggernaut XL v9 | dpmpp_2m / karras, 30 steps, cfg 5 | 0.5 | 256 | Other SDXL checkpoints are untested |

These come from one seed and four references per model, comparing tile_mix 0, 0.25 and 0.5, so treat them as starting points. On FLUX.1, Juggernaut and Qwen Image, 256 was the largest radius tested.

The full comparison, with the settings under every panel:

All models, references and modes

The painted portrait shows the limit of AdaIN: on Klein and Juggernaut the hair stays mostly dark in every AdaIN panel, while tile mode turns it white and copies more of the reference. On FLUX.1 the hybrid reaches light grey hair, and on Qwen Image it adds iridescent streaks, where pure adain looks cleaner. The portrait ran on ColorFix Patcher, the other references on the older nodes at the same settings. Workflows: Klein, FLUX.1, Juggernaut, Qwen Image.

Workflows behind the test grids above are in test_workflows/, in API format. Most use the older nodes.


Workflow 1 — SDXL + ColorFix + ControlNet + Tile

Load Image ──► VAE Encode ──► TileColorFixPatcher ──► KSampler
Load Checkpoint (SDXL) ───────────────────────────────────────► KSampler
                         ControlNetTileApply ──────────────────► KSampler

Nodes used:

  • Load Image → VAE Encode → connect to ref_latent on Tile ColorFix Patcher
  • Load Checkpoint → connect MODEL to Tile ColorFix Patcher
  • Tile ColorFix Patcher → patched MODEL → KSampler
  • Load ControlNet + Load Image → Apply Ultimate ControlNet → CONDITIONING → KSampler

Key parameters:

  • blur_k — controls the color transfer radius (default 8, range 3–32)
  • weight — color fix strength (0.0 = none, 1.0 = full)
  • blur_mode — box (A1111 original) for exact A1111 match, gaussian for smoother blending

Workflow 2 — Flux (Dev / Schnell / Klein) + ColorFix + ControlNet + LoRA

Load Image ──► VAE Encode (Flux) ──► ColorFixPatcher ──► KSampler
Load Checkpoint (Flux) ─────────────────────────────────► KSampler
Load LoRA ──────────────────────────────────────────────► KSampler

Nodes used:

  • Load Image → VAE Encode (Flux VAE) → connect to ref_latent on ColorFix Patcher
  • Load Checkpoint → Load LoRA → connect MODEL to ColorFix Patcher
  • ColorFix Patcher → patched MODEL → KSampler

Encode the reference with the VAE that matches the model: Flux VAE for FLUX.1 (16 channels), flux2-vae for FLUX.3 Klein (128 channels).

ColorFix Patcher inputs (defaults are the settings for an unrelated reference; for img2img or upscaling, use tile (spatial) with start_percent 0):

  • transfer_mode — adain (global) (default), tile (spatial), or adain mean-only (global tone)
  • blur_radius_px — radius in image pixels, converted per model (default 256, try 192 in tile mode). Used by tile mode and tile_mix
  • weight — color fix strength (default 1.0)
  • tile_mix — AdaIN modes: share of tile transfer blended over the AdaIN result (default 0.5; lower it if the reference's backdrop bleeds onto your subject)
  • start_percent — skip the fix before this point of sampling (default 0.15)
  • blur_mode — gaussian (smoother) (default) or box (A1111 original)
  • blur_radius_start_px — optional: start the radius here and move linearly to blur_radius_px by the end (default 0 = constant)
  • sharpness — optional, tile mode only: direct high-pass detail boost (default 0.0)

Older workflows with Flux Tile ColorFix Patcher keep working. That node also has the optional inputs transfer_mode, tile_mix, start_percent, blur_k_start and blur_radius_px, the last of which overrides blur_k.


Installation

Clone into your ComfyUI custom_nodes folder:

cd ComfyUI/custom_nodes
git clone https://github.com/ihorpankin/comfyui-colorfix-v3.git

Restart ComfyUI. The nodes will appear under the colorfix-v3 category.


How It Works

The tile_colorfix algorithm splits an image into low-frequency (color/tone) and high-frequency (detail/texture) components using a blur kernel. At each denoising step, the low-frequency component of the generation is replaced with the low-frequency component of the reference image. This forces the model to match the color palette of the reference while still generating its own detail.

  • Low frequency — extracted via box/gaussian blur
  • Color swap — reference low-freq replaces generated low-freq
  • High frequency preserved — AI-generated texture and detail remain untouched

This is a port of the original A1111 implementation to native ComfyUI model patching via set_model_sampler_post_cfg_function. ColorFix Patcher's AdaIN mode uses the same patching point but matches global statistics instead of swapping frequencies.


Architecture

comfyui-colorfix-v3/
├── __init__.py           # Node registration
├── layer1_nodes/         # ComfyUI-visible nodes (model patchers)
│   ├── colorfix_universal_patcher.py
│   ├── colorfix_patcher.py
│   ├── colorfix_sharp_patcher.py
│   ├── controlnet_apply.py
│   ├── controlnet_stack.py
│   ├── controlnet_multi_apply.py
│   ├── flux_colorfix_patcher.py
│   ├── flux_colorfix_sharp_patcher.py
│   ├── flux_controlnet_apply.py
│   └── flux_controlnet_multi_apply.py
└── layer2_core/          # Internal algorithm
    ├── blur.py           # Box / Gaussian blur kernels
    ├── color_swap.py     # Low-frequency color transfer, AdaIN
    └── sampler_callback.py  # Post-CFG callback factory