Y7Nodes for ComfyUI
A collection of utility / quality-of-life nodes for ComfyUI. Probably only useful to me.
Nodes (23)
The sampler dropdown that won't take a wire — until this node
Stop doing aspect-ratio math in your head — drag it instead
The boring node that finishes your captioning pipeline
Why your 77-token CLIP prompt is lying to you
The color-shift fix for every inpainting job that leaves a tint
The crop node that stops 'dimensions must be divisible by 16' errors
Multi-reference Flux.2 Klein edits without the conditioning spaghetti
The one-node fix for upscaling past Flux.2 Klein's ceiling
The Flux.2 sampler that can't drift out of sync
The image loader that remembers where every file came from
An A/B slider for images, right on the canvas
Pad for outpainting without breaking the 8-pixel rule
One dropdown for every model family's native resolutions
Stitch 2 to 8 images side by side, without the manual resize dance
Load Image, but it actually sees your subfolders
Paste an edited crop back — without knowing your image dimensions
A prompt enhancer that borrows ComfyUI's text encoder instead of hauling in a second model
The resolution calculator with the fine megapixel knob you didn't know you wanted
Scale by a multiplier — and stop landing on resolutions that break your model
Set a pixel budget, not a size — the megapixel-normalizing resize node
The 'what is actually flowing through this wire?' node
Why does your Flux prompt cut off? This node shows you the exact wall.
The most boring node in the pack, and one of the most useful
ComfyUI-Y7Nodes
A collection of utility / quality-of-life nodes for ComfyUI - Probably only useful to me. There's really nothing new here. Some nodes are modifications of of existing custom nodes with additional features that suit my particular needs.
Installation (ComfyUI Manager)
This is the better way to install:
- Open
ComfyUI Manager- →
Custom Nodes Manager - → Search for
Y7orY7Nodes. - Install.
- Restart Restart ComfyUI
- →
Installation (Manual)
-
Clone this repository into your ComfyUI custom_nodes directory:
cd /path/to/ComfyUI/custom_nodes git clone https://github.com/yushan777/ComfyUI-Y7Nodes -
Install Dependencies
# activate your venv (if you have one) # Linux/macOS source venv/bin/activate or # Windows venv/Scripts/activate pip install -r requirements.txt -
Restart ComfyUI if it's already running.
Nodes
Y7 Aspect Ratio Picker
Interactive 2D canvas for picking image width and height by dragging.
<img src="assets/aspect_ratio_picker.jpg" alt="aspect ratio picker" width="50%"/> <details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Click or drag anywhere in the canvas to set width (X axis, left→right) and height (Y axis, bottom→top).
- A filled rectangle shows the selected proportions; the dot marks the current position.
- The simplified aspect ratio (e.g. 16:9, 4:3, 1:1) is displayed at the bottom of the canvas.
- Current width and height values are shown in the right panel. Double-click either value to type a number directly.
- Click the Swap button (below the height value) to swap width and height (portrait ↔ landscape).
- Snapping to step increments is on by default. Hold Shift while dragging to temporarily disable snapping.
- Node properties (right-click → Properties):
valueX,valueY,minX,maxX,minY,maxY,stepX,stepY,snap,dots.- The right panel shows width, height, simplified ratio (e.g. 16:9), and total megapixels (e.g. 1.0MP).
- Outputs
widthandheightas INT.
Y7 Show Anything
Takes input from any (most?) nodes and displays it in a readable format and provides a Copy Text button for easily copying the displayed content.
<img src="assets/show_anything.jpg" alt="show anything" width="100%"/> <details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Based on other nodes that already work just fine. I just always wanted one with a
copy textbutton for easy copying of long generated prompts (for editing or use elsewhere). It will primarily showstring, integer, float and booleanvalues directly but will also (try to) display tensor data.
Y7 Text
A plain multiline text box that passes its contents straight through to a
STRINGoutput. Useful as a shared prompt source that several nodes can read from.
Y7 Image Stitcher
Stitches 2–8 images side-by-side or top-to-bottom. The
<details> <summary>ℹ️ <i>See More Information</i></summary>image_countwidget controls how many image sockets are shown on the node.</details>
- Set
image_count(2–8) to show exactly that many image input sockets. Sockets are added or removed live as you change the value.- Side-by-Side (Horizontal): all images are resized to match the first image's height, then concatenated left-to-right.
- Top-and-Bottom (Vertical): all images are resized to match the first image's width, then concatenated top-to-bottom.
- Unconnected sockets within the count are skipped gracefully.
- Output is a single
IMAGEtensor.
Y7 Image Compare
Compares two images with a draggable slider for interactive side-by-side comparison directly on the node.
<details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Connect
image_a(required) andimage_b(optional), then drag the slider to revealimage_aoverimage_b.- Two blend modes:
normal(slider wipe) anddifference(highlights variations between the two images).- The preview updates live as the slider is moved or the blend mode is changed, and persists across workflow-tab switches.
- The node auto-resizes to match the aspect ratio of the input images; slider position and blend mode are saved with the workflow.
- Right-click over the image for
Open Image/Save Imageoptions.- Preview-only node with no outputs.
- Based on
Eses Image Compareby Eses Nodes.
Y7 CLIP Token Counter
Takes text (string) as input and, using the CLIP tokenizer, displays token count and more:
<img src="assets/clip_token_count.jpg" alt="clip token counter" width="100%"/> <details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Displays the number of tokens in the text
- Whether the input exceeds the model's token limit (77 - Including BOS and EOS)
- The final token within the range, along with surrounding context
- All tokens within the limit, plus any overflow tokens beyond it
- Copy Text button: copies the contents displayed in the text widget
- Pass-though output for original text
Y7 T5 Token Counter
Takes text (string) as input and, using the T5 XXL tokenizer, displays token count and more:
<img src="assets/t5_token_count.jpg" alt="t5 token counter" width="100%"/> <details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Displays the number of tokens in the text
- Whether the input exceeds the model's token limit (256 or 512 - Including EOS)
- The final token within the range, along with surrounding context
- All tokens within the limit, plus any overflow tokens beyond it
- Copy Text button: copies the contents displayed in the text widget
- Pass-though output for original text
Y7 Prompt Enhancer (Native)
Takes any basic prompt and enhances it using a text encoder that ComfyUI has already loaded, via a
<details> <summary>ℹ️ <i>See More Information</i></summary>CLIPinput. Downloads nothing, loads nothing, and leaves all VRAM management to ComfyUI. Reasoning is separated from the prompt automatically.Where a typical prompt enhancer node owns its model (downloading it, loading it through HuggingFace transformers, and managing when to free it), this node does none of that. You load a text encoder with a standard
CLIPLoaderand connect it. ComfyUI handles loading, device placement and offloading exactly as it does for any other model in your workflow.Supported models
Any text encoder with a native generation path:
| Model | Variants | | --- | --- | | Gemma 4 | E2B, E4B, 31B, 12B unified | | Gemma 3 | 12B (including the LTX-2 text encoder built on it) | | Qwen3 | 0.6B, 2B, 4B, 8B | | Qwen3.5 | 0.8B, 2B, 4B, 9B, 27B | | Qwen3-VL | 4B, 8B |
Not supported — T5 (all sizes), UMT5, CLIP-L, CLIP-G, Gemma 2, LLaMA-3.1. These have no text generation path; the node detects this and tells you, rather than failing with an obscure error deep inside the encoder.
Model format
Safetensors only, placed in
models/text_encoders/. GGUF will not work — ComfyUI core has no GGUF loader (.ggufis not even a recognised model extension), and for Gemma 4 the tokenizer is embedded inside the safetensors file, so a converted GGUF would be missing it.For Gemma 4 the
CLIPLoadertypedropdown is ignored — the model is detected from the weights themselves, so any value in that dropdown works.Gemma 4 weights: https://huggingface.co/Comfy-Org/gemma-4/tree/main/text_encoders
ComfyUI └── models └── text_encoders └── gemma4_e4b_it_bf16.safetensorsInputs
clip: A generation-capable text encoder fromCLIPLoadertext: Your basic prompt. Accepts a connection from any string node.instruction: The instruction placed before your text. Edit to change the enhancement style.max_length: Maximum new tokens to generate (64–32768, default 2048). Not the context window. Reasoning is spent from the same budget, and the KV cache reserves roughly 84KB of VRAM per token up front.temperature: 0.0–2.0, default 1.0 (Google's recommended value for Gemma). 0 switches to greedy decoding.top_k: 0–1000, default 64 (Google's recommended value). 0 disables.top_p: 0.0–1.0, default 0.95 (Google's recommended value). 1.0 disables.seed: Change it to re-roll — identical inputs return a cached result.thinking: Let the model reason before answering.Outputs
thinking_output: The model's reasoning, if it produced anyenhanced_prompt: The enhanced prompt, with all reasoning removedOn reasoning
Gemma 4 writes its reasoning into a thought channel, and ComfyUI's decoder deliberately preserves that text instead of discarding it. Turning
thinkingoff only primes the model to skip reasoning — Gemma 4 often reasons anyway, which is why ComfyUI's own Generate Text node can hand back a wall of planning notes with the actual prompt buried at the end.This node always separates the two, including the awkward case where the model reasons straight past the primed channel and closes it with an unmatched tag. If
</details>enhanced_promptcomes back empty, the model spent the entiremax_lengthbudget reasoning — raise it, or lowertemperature.
Y7 Image Batch Path
Load a batch of images from a directory and output them as a list of image tensors with matching file paths. Designed to pair with Caption Saver and a VLM node for batch captioning workflows.
<details> <summary>ℹ️ <i>See More Information</i></summary>Supports jpg, jpeg, png, and webp. Images are EXIF-transposed and converted to RGB float32 tensors.
Connect
IMAGEto a VLM node andIMAGE_PATHto Caption Saver. The path list tells Caption Saver exactly where to write each.txtfile.Inputs:
image_dir: Path to the directory containing imagesbatch_size: Number of images to load (0 = all)start_from: 1-based index of the first image to load — useful for resuming part-way through a directorysort_method: Load order —sequential(alphabetical),reverse, orrandomOutputs (both are lists):
IMAGE: List of image tensors, one per fileIMAGE_PATH: List of full file paths matching each image tensorNote: When
</details>sort_methodisrandom, the node re-evaluates on every run.
Y7 Caption Saver
Save a caption string as a
<details> <summary>ℹ️ <i>See More Information</i></summary>.txtfile next to the source image, using the same filename stem (e.g.cat.jpg→cat.txt).Designed to pair with Image Batch Path and a VLM node: connect
IMAGE_PATHfrom Image Batch Path and the captionSTRINGfrom the VLM node.Compatible with any node that outputs a STRING. Examples: Florence2, MiniCPM, LLaVA, Qwen-VL, etc.
Inputs:
string: The caption text to write (must be connected)image_path: Full path to the source image (must be connected — e.g. from Image Batch Path)overwrite: If true, overwrites any existing.txtfile. If false, appends a counter to avoid overwriting (e.g.cat_01.txt,cat_02.txt)This node has no outputs — it is a terminal/output node.
</details>
Y7 Image Size (Presets)
Select predefined image size/aspect ratios from a named preset set. Provides width and height outputs.
<details> <summary>ℹ️ <i>See More Information</i></summary></details>
- Provides outputs for
widthandheight(INT).- The
presetwidget selects the active dimension set:default,flux.2,qwen-image, orcustom*.- The
dimensiondropdown updates dynamically to show only the dimensions for the selected preset.- Select
Customfrom the dimension dropdown to use manually enteredcustom_w/custom_hvalues.- The
custom*preset loads fromcustom_dimensions.jsonin thenodesdirectory; falls back todefaultif the file is missing or invalid. Seecustom_dimensions_example.jsonfor the expected format.
Y7 Resolution Selector
Calculate width and height from an aspect ratio and a megapixel target, rounded to the nearest multiple.
<details> <summary>ℹ️ <i>See More Information</i></summary>A clone of ComfyUI's built-in V3
ResolutionSelectornode, with a finer-grainedmegapixelsstep (0.01 instead of 0.1) and the resolution displayed directly on the node after execution.Inputs:
aspect_ratio: The target aspect ratio (e.g.1:1 (Square),16:9 (Widescreen))megapixels: Target total megapixels (default: 1.0, range: 0.1–16.0)multiple: Rounds the result to the nearest multiple of this value (default: 8)Outputs:
</details>
width: Calculated width in pixels (INT)height: Calculated height in pixels (INT)
Y7 Scale Image By
Scales an image by a multiplier while preserving aspect ratio.
<details> <summary>ℹ️ <i>See More Information</i></summary>Multiplies both width and height by
scale_by, then resamples using the chosen method. The output resolution is displayed directly on the node after execution.Inputs:
image: The input image to scaleupscale_method: Resampling algorithm —nearest-exact,bilinear,area,bicubic, orlanczosscale_by: Multiplier applied to both dimensions (default: 1.0, range: 0.01–8.0)resolution_steps: Snap output dimensions to the nearest multiple of this value (default: 8). Common values: 8, 16, 64Outputs:
</details>
image: The scaled imagewidth: Output width in pixels (INT)height: Output height in pixels (INT)
Y7 Scale Image to Total Pixels
Scales an image to a target total pixel count (in megapixels) while preserving aspect ratio.
<details> <summary>ℹ️ <i>See More Information</i></summary>Computes a uniform scale factor so that
width × heightequals the target megapixel count, then resamples using the chosen method. The output resolution is displayed directly on the node after execution.Inputs:
image: The input image to scaleupscale_method: Resampling algorithm —nearest-exact,bilinear,area,bicubic, orlanczosmegapixels: Target total pixel count in megapixels (default: 1.0, range: 0.01–16.0)resolution_steps: Snap output dimensions to the nearest multiple of this value (default: 8). Common values: 8, 16, 64Outputs:
</details>
image: The scaled imagewidth: Output width in pixels (INT)height: Output height in pixels (INT)
Y7 Crop to Nearest Multiple
Automatically crops images to ensure dimensions are divisible by a specified value (e.g., 8 or 16), with visual preview of crop areas and independent horizontal/vertical control.
<details> <summary>ℹ️ <i>See More Information</i></summary>Many AI models require image dimensions to be divisible by specific values (typically 8 or 16) for proper processing. This node automatically checks image dimensions and crops them to meet these requirements while giving you precise control over where the crop occurs.
Key Features:
- Visual Preview: Shows original image with semi-transparent red overlay indicating areas that will be cropped
- Independent Control: Separate horizontal and vertical crop position settings
- Smart Logic: Only crops dimensions that need adjustment, ignoring dimensions that are already aligned
- Flexible Positioning: Choose
center,left,right,top,bottom, ornonefor each axis- Informative Output: Provides detailed status messages about dimensions and any cropping performed
- On-Node Display: Shows the cropped dimensions (e.g., '1024 x 768') directly on the node after execution
Inputs:
multiple: The value dimensions must be a multiple of (default: 16). Common values are 8 or 16 for most AI modelsh_crop: Where to keep content when width needs adjustment -center,left,right, ornonev_crop: Where to keep content when height needs adjustment -center,top,bottom, ornoneOutputs:
crop_preview: Original image with red overlay showing what will be cropped (useful for previewing before committing)cropped_image: The cropped result (or original if no cropping needed)info: Status message with dimension details and cropping informationBehavior Notes:
- Crops to the nearest multiple down (e.g., 721 → 720 with multiple=16)
- Setting a crop position to
nonedisables cropping for that dimension- When using
centerwith odd-numbered pixel differences, integer division rounds down (e.g., width=721 removes 1px from right only)- This slight bias is standard in image processing and is minimal (max 1 pixel difference)
Use Cases:
</details>
- Preparing images for models that require specific dimension constraints
- Cropping images from one dimension while keeping the other intact
- Quick visual verification of crop areas before applying
Y7 Color Match (Masked)
Colour matches a target image to a reference while excluding masked regions from the calculation on both images.
<details> <summary>ℹ️ <i>See More Information</i></summary>The use case is inpainting. Change a red car to blue and the rest of the image often picks up a colour shift, but a plain colour-match node will read the new blue car as part of the picture and skew the correction. This node calculates the transfer from the non-masked areas only (the background), applies it to those same areas, and leaves the inpainted region untouched.
Inputs:
image_ref: Reference image — e.g. the original, before inpaintingimage_target: Image to correct — e.g. the result after inpaintingmethod: Colour transfer method —mkl,hm,reinhard,mvgd,hm-mvgd-hm, orhm-mkl-hmmask(optional): White (1.0) marks the region to exclude from matching. With no mask connected, the whole image is matchedstrength(optional): Blend between the original and the corrected result (0.0–1.0, default 1.0)feather(optional): Blur radius in pixels for the mask edge transition (0–100, default 0)Outputs:
image: The colour-corrected imageRequires the
</details>color-matcherpackage (included inrequirements.txt). Based on the ColorMatch node from kijai's ComfyUI-KJNodes.
Y7 Paste Cropped Image Back
<img src="assets/paste_cropped_image_back.jpg" alt="paste cropped image back" width="100%"/>Paste a cropped image back onto a base image post-editing at a region defined by edge-relative coordinates. Varient of the WAS equivalent, except
<details> <summary>ℹ️ <i>See More Information</i></summary>rightandbottomare offsets measured inward from the right and bottom edges.Sometimes you may want to change or refine a specific area of an image without affecting the rest too much — for example, fixing a face, hand, or background detail after generation. A typical workflow is to crop the region, run it through img2img or inpainting, then paste the result back using this node.
Works well with the OLM Drag Crop custom node, which lets you visually drag-select a crop region and outputs the crop coordinates directly — those coordinates can be wired into this node's
top,left,right, andbottominputs.The paste region is computed as:
x1 = lefty1 = topx2 = image_width - righty2 = image_height - bottomThis makes it easy to target edge-relative regions without knowing the image dimensions in advance — e.g., set
right=256, bottom=256to always paste into the bottom-right 256-wide strip of any image.The
image_cropis always resized to exactly fit the paste region. If it was upscaled for editing (e.g. sent through img2img at a higher resolution), it will be scaled back down during pasting. There is no aspect-ratio preservation — if the aspect ratio of the crop image differs from the paste region, it will be stretched to fit and appear distorted.Inputs:
image_orig: Base image to paste ontoimage_crop: Image to paste into the defined region (resized to fit)left/top: Pixel offsets from the left and top edgesright/bottom: Pixel offsets inward from the right and bottom edgescrop_blending: Feathering/blending amount at paste edges (0.0–1.0)crop_sharpening: Number of sharpening passes applied before pasting (0–3)Outputs:
</details>
IMAGE: Base image with crop pasted inMASK: The blended mask used for the paste operation
Y7 Pad Image for Outpainting
Pads an image ready for outpainting, with the padding snapped to a chosen step and a choice of what to fill the new area with.
<details> <summary>ℹ️ <i>See More Information</i></summary>A rework of ComfyUI's built-in
ImagePadForOutpaint. Three differences: padding is rounded to a multiple ofstepso the padded canvas stays a size the model is happy with, the new area can be filled with something more useful than flat grey, and the feathering is vectorised rather than looping over every pixel in Python.The fill matters more than it sounds like it should — it all gets painted over during the outpaint, but a plausible starting colour tends to give a better result than flat grey.
Inputs:
image: The image to padstep: Padding is rounded to a multiple of this value (default 16). Also sets how far the +/- arrows move each sidefill: What to put in the new area —grey(flat 50%, same as the built-in node),edge replicate(smears the outermost pixels outwards),mirror(reflects the image back on itself),blurred edge(a soft blur of the nearby colours), ornoise(random noise in the image's own colours)feathering: Width in pixels of the soft fade at the join between the original image and the new area (default 40; 0 gives a hard edge)left/top/right/bottom: Pixels to add to each edgeOutputs:
</details>
image (original): The image exactly as it came in, unpaddedimage (padded): The image on the enlarged canvas, with the new area filledmask: White over the new area, black over the original image, feathered ramp in betweenwidth/height: Dimensions of the padded image (INT)
Sampler Select (Name)
Select a sampler by name and output it as a linkable string — works around ComfyUI's built-in KSampler nodes not exposing sampler name as a connectable input.
Y7 Flux.2 Klein Edit Multi-Ref
All-in-one image editing for Flux.2 Klein with multiple reference images. Pick the image to edit on the node, mask it, wire in extra references, and get back a ready-to-sample reference latent plus patched positive/negative conditioning.
<details> <summary>ℹ️ <i>See More Information</i></summary>Flux.2 / Klein accepts a list of reference latents on the conditioning, so extra images can be wired in as additional visual context — a character sheet, a style reference, a product shot — alongside the image actually being edited. The list is ordered: the on-node
imageis reference 1, thenref_image_2,ref_image_3and so on in socket order. The extra sockets grow as you connect them, up toref_image_8.Masking applies to the on-node image and nothing else, whichever route it arrives by — painted in the mask editor, or wired into
external_mask. The extra references are IMAGE-only and have no mask of their own; a mask ends up as the latent'snoise_mask, which has to line up cell-for-cell with the latent being denoised, and an arbitrary reference image at an arbitrary size has nothing to align to.Klein has no mask input of its own and is not a fill/inpaint model, so the mask survives only as that
noise_mask: the sampler restores everything outside the painted area after each step, in latent space at 1/16 resolution. Two consequences that pull in opposite directions:
- For sampling, feathering is close to a no-op — 4px is bit-identical to no feather once the mask is downsampled 16x, and only ~32px puts real intermediate values into more than one latent cell (where it crossfades partially-denoised latents into a smeared seam rather than a blend).
- For a pixel-space composite downstream (
ImageCompositeMasked, or Y7 Paste Cropped Image Back), the same feather survives at full resolution, where 4–8px is the difference between a hard cut and a soft join. That is whybinary_maskdefaults to off — it would flatten the ramp before either consumer sees it.Leave the sampler's
denoiseat 1.0. The unmasked area is restored every step regardless, so lowering it does nothing but weaken the edit.Prompting: there is no special syntax for addressing the references. The text encoder never sees the images — they reach the transformer only as latent tokens appended to the sequence, in list order. Refer to them in plain English by position, always paired with a noun: "Have the man in Figure 1 put on the clothes from Figure 2, and change the background to a savannah".
Figure Nis the wording in ComfyUI's own multi-reference Klein template;image 1/the first imageis the same kind of positional reference. Neither is a real token, so both are worth trying if a prompt is not binding to the reference you meant.Inputs:
vae: Used to encode the edited image and every referenceimage: The image to edit, picked from the ComfyUI input folder (with upload button and preview). Right-click → Open in MaskEditor to paint a masktarget_megapixels: Resamples the edited image to this pixel budget before encoding (default 1.0; 0 leaves it alone). This is the latent actually being denoised, so it also sets the output resolution. Klein is built for around 1.0ref_megapixels: The same budget, applied to each reference separately (default 1.0; 0 leaves them alone). It does not affect output size. One image plus six references at 1.0 is seven megapixels of work — turn this down first (try 0.5) if you run slow or run out of VRAMcrop_2_nearest_16px: Centre-crops the edited image, its mask and every reference down to a multiple of 16 before encoding (default on)expand_mask: Grows the painted mask outwards by this many pixels (default 16 — one full latent cell, which compensates for a tightly painted edge being clipped inward by the downsample). Try 24–32 for hair, fur or soft edgesfeather_mask: Gaussian softening of the mask edge (default 8). See the note above on where this actually mattersbinary_mask: Applied last — thresholds the mask to hard edges (default off)external_mask(optional): A mask from anywhere else, used instead of a painted one. Note: with Load Image (as Mask) on a plain black-and-white file, set its channel tored— onalphait hands back an empty maskref_image_2…ref_image_8(optional): Extra reference images. Connect one and another empty socket appearspositive/negative(optional): Conditioning to extend with the reference latentsOutputs:
reference_latent: The encoded (and resampled) edited image, ready to samplepositive/negative: Conditioning with the reference latents attachedpreview_image: The edited image as it was actually encodedpreview_mask: The processed mask, after expand/feather/binarydebug: What the node actually did — sizes in and out, mask state, every reference socket, and the token cost of the whole reference list. Wire it into Y7 Show Anything when something looks wrongWorks with all flux.2-klein variants (base, distilled, 4B/8B text encoder).
</details>
Y7 Flux.2 Sampler
All-in-one Flux.2 sampler:
<details> <summary>ℹ️ <i>See More Information</i></summary>RandomNoise,KSamplerSelect,Flux2Scheduler,CFGGuiderandSamplerCustomAdvancedcompacted into a single node.Sampling a Flux.2 (including Klein) model normally means wiring five nodes together. This node takes one input side — model, positive, negative, latent — and gives back the denoised latent, ready for VAE decode.
There are no width/height widgets.
Flux2Scheduler's are dropped because the sigma schedule'sseq_lenis derived fromlatent_image's own dimensions instead, so it cannot drift out of sync with the latent being sampled.Inputs:
model: The diffusion model to sample withlatent_image: The latent to denoise — e.g. from Empty Flux.2 Latent Image, or from the Klein Edit nodepositive/negative: Conditioning. The negative is ignored by the guider whencfgis 1.0seed: Seed for the initial noisecfg: Guidance scale (default 1.0 — Klein checkpoints are typically guidance-distilled)sampler_name: Which sampler algorithm to step with (defaulteuler)steps: Sampling steps (default 4 — distilled Klein checkpoints commonly need no more)denoise: How much of the schedule to run (default 1.0). It shortens the run as well as the noise level, so at 4 steps only a handful of settings are reachable, and Flux.2's schedule means even 0.5 keeps under 10% of the incoming image. Leave it at 1.0 unless you specifically want thisOutputs:
</details>
output: The denoised latent
Y7 Flux.2 Klein Upscaler (Tiled)
Enlarges an image and repaints it one tile at a time with Flux.2 Klein, so you can go far past the size the model or the card could manage in one pass. The sampler, scheduler and guider are built in.
<details> <summary>ℹ️ <i>See More Information</i></summary>Each tile is treated as a small inpaint: the middle is regenerated while a band of surrounding pixels is held frozen as context, so neighbouring tiles agree with each other instead of each inventing its own idea of what is there. Nothing larger than a single tile is ever encoded or decoded, which is what keeps VRAM flat as the canvas grows —
tile_size, not the finished size, is what determines peak memory.Ported from ComfyUI_KleinTiledUpscaler by Gavr728 (MIT). The frozen-padding anchoring, the separable blend profiles and the shared canvas noise field are that project's ideas. What is done differently here:
- All-in-one. Upstream needs CFGGuider + KSamplerSelect + Flux2Scheduler (and usually SplitSigmasDenoise) wired in front of it. This node builds the guider, the sampler and the schedule itself, and gives the negative conditioning the same per-tile treatment as the positive.
- Per-tile sigma schedule. Flux.2's schedule shift is a function of how many tokens are being sampled, and a tile is not the whole canvas. Every tile gets a schedule built from its own latent size.
- Partition-of-unity blending instead of sequential lerp plus a
mask_blurwidget. Tile weights are complementary raised-cosine ramps centred on each shared boundary, summing to exactly 1.0, so seams are correct by construction and there is nothing to tune.- No full-canvas VAE encode, which is the exact thing tiling exists to avoid.
- Tile layout rewritten — the grid is derived once, the remainder spread evenly across tiles, and the result printed in the report.
- Per-tile sampler seed, so ancestral and SDE samplers do not repeat the same texture across the picture.
Inputs:
model/vae: The Klein model and the VAE used for every tile encode/decodeimage: The picture to enlarge. A batch is processed one image at a timepositive: Keep it a short description of the picture as a whole, or leave it empty — it is applied to every tile, so anything naming a specific object will try to put that object in all of themnegative: Ignored unlesscfgis above 1.0seedscale_factor: How much bigger to make the picture (default 2.0). 1.0 is a useful setting — no enlargement, but every tile is still repainted, which turns the node into a sharpen/refine pass. With 1.0, leaveupscale_modelunplugged and userefine_strength(0.85–0.92) to control how much changestile_size: Roughly how big each tile is (default 1024). This is what decides VRAM. Turn it down if you run out of memory, up if tiles are inventing detail that does not belongoverlap: How far each tile looks past its own edges (default 128). Raising it helps things that run across a seam — a roofline, a horizon — stay joined upsteps: Per tile (default 4)cfg: Leave at 1.0 for distilled checkpoints. Above 1.0 every tile costs twice as muchsampler_namedenoise: How much each tile may change (default 1.0, which is normally what you want here)color_match: Nudges each finished tile back towards the colours of the enlarged original so tiles do not drift apart in tone (defaultmkl;offdisables)refine_strength(advanced): Restrains the model at every sampler step rather than fading the finished tile afterwards, which makes it a better detail dial thandenoise. 1.0 repaints completely; 0.92 is a good first try; 0.85 is strongly held backreference_source(advanced): What each tile is told it is looking at —enlarged(always the plain enlargement, predictable) orprogressive(the tile's surroundings as they stand, including finished neighbours; more consistent, but mistakes can compound). Tryenlargedfirstupscale_model(optional): An ESRGAN-style upscaler to enlarge with before the tiles are repainted; plain bicubic is used without one. Pick a clean, neutral model rather than a sharp one — the enlargement becomes the frozen context and the reference every tile works from, so halos and invented texture get copied rather than fixed.4xRealWebPhoto_v4_dat2,4xNomosUniDAT_otfandRealESRGAN_x4plusare good; anything with "Sharp" in the name is not. Its result is always resized to exactlyscale_factor, so a 4x model at scale_factor 2 is fine (better, even), but a 2x model at scale_factor 4 leaves half the enlargement to bicubicOutputs:
</details>
image: The finished picturelatent: The same picture in latent form, blended with identical geometry, so it can be fed onward without a re-encodereport: Canvas size, the grid chosen, tile and crop sizes, and a check that the blend weights really do sum to 1
Y7 Load Image (subfolders)
The native ComfyUI Load Image node only lists files directly in the
inputfolder. This node is identical except it walks the fullinputdirectory tree, so images organised into subdirectories appear in the dropdown.Outputs
image(IMAGE) andmask(MASK), same as the built-in node.
Example Workflows
Example workflows can be found in the example_workflows directory.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Credits
- ShowAnything node is based on "Show Any" from yolain's ComfyUI-Easy-Use custom nodes and "Show Any To JSON" from crystian's ComfyUI-Crystools custom nodes, with additional formatting controls and a Copy Text button.
- Help popup system is based on the implementation from Kosinkadink's ComfyUI-VideoHelperSuite.
- Color Match (Masked) is based on the ColorMatch node from kijai's ComfyUI-KJNodes, using the color-matcher library.
- Flux.2 Klein Upscaler (Tiled) is ported from ComfyUI_KleinTiledUpscaler by Gavr728 (MIT).