Nodes/4A NovelAI/NAI Image Input
ComfyUI Node

NAI Image Input

Img2img and inpainting that won't fight you over resolution

By tsukino4a·Created 20 days ago·Updated 7 days ago· 5
NAI Image Input
  • image
  • mask
  • image_source
strength0.70
noise0.00
scale_to_budgettrue
size_classNormal
upscalefalse
upscale_scale1.5

Text-to-image is the easy case. The moment you want to rework an existing image - restyle it, inpaint a section - you need the input handled right, and that's what NAI Image Input exists for. It sits between your image and NAI Sampler and does one job that sounds trivial and isn't: it decides what kind of generation you're doing and makes sure the Sampler doesn't stretch your source into a shape you never asked for.

How it decides the mode

The clever bit is that the mode isn't chosen by which sockets you wired. It's read from the image and mask contents:

  • No image: text-to-image, using the Scheduler/Sampler dimensions.
  • Image + empty or unpainted mask: image-to-image. An empty mask can stay connected - the pack checks whether the mask actually has painted content, not whether the socket exists.
  • Image + painted mask: inpainting.

That last rule is worth internalizing, because it's the opposite of how most ComfyUI mask plumbing behaves: a connected-but-empty mask won't silently flip you into inpainting mode.

The resolution rule that saves your images

In the img2img and inpainting modes, Image Input owns the generation size - it doesn't blindly copy the Sampler's width/height. It keeps the source aspect ratio and either:

  • scales to a pixel budget via scale_to_budget plus size_class (Small, Normal, Large, Wallpaper), preserving aspect ratio, or
  • upscales 1.5× via the upscale toggle (the upscale_scale field is fixed at "1.5" for now), using NovelAI's official Enhance rule - multiply each side, round up to the nearest 64 - then scaling back down if a side would exceed 2048, or
  • retains approximately the source pixel count.

upscale and the pixel-budget toggle are mutually exclusive, so you can't accidentally do both. The point of all this is in the README, stated plainly: it prevents an unrelated Sampler size from unexpectedly stretching your input image. This is the node that stops the "why did my inpaint come out squished" complaint before it starts.

Inputs and output

Beyond the ones above, the two you'll actually set are strength (default 0.7 - how far from the source you're willing to go, 0–1) and noise (default 0 - how much random grain gets added on top). The image and optional mask sockets are self-explanatory. There's one output, image_source, and it plugs into NAI Sampler's optional image_source input. Wire that up and the Sampler switches modes and derives its effective dimensions from this node's decisions.

Install and gotchas

Part of the ComfyUI-4A-NovelAI pack - ComfyUI Manager (search 4A NovelAI) or git clone https://github.com/tsukino4a/ComfyUI-4A-NovelAI.git into custom_nodes, run python install.py, restart. No model files to download (the actual model lives on NovelAI's servers), just the msgpack dependency.

Two things to remember: img2img and inpainting calls are sent once, never retried by the pack (see the retry policy in the README) - and they cost Anlas, so a mistyped strength isn't a free do-over. Check your mask is actually painted before queueing.

Category4A NovelAI

Inputs (8)

NameTypeDefaultDescription
imageIMAGE
strengthFLOAT0.700–1
noiseFLOAT0.000–1
scale_to_budgetBOOLEANtrue
size_classCOMBONormal4 options: Small, Normal, Large, Wallpaper
upscaleBOOLEANfalse
upscale_scaleCOMBO1.51 options: 1.5
maskoptMASK

Outputs (1)

NameTypeDescription
image_sourceNAI_IMAGE_SOURCE