Nodes/KJNodes for ComfyUI/MOSS-Image Prompt Builder KJ
ComfyUI Node Runs on cloud

MOSS-Image Prompt Builder KJ

MOSS-Image Prompt Builder KJ

By kijai·Created 3 years ago·Updated 13 days ago· 3,465
MOSS-Image Prompt Builder KJ
  • image
  • bboxes
  • prompt
  • preview
  • bboxes
  • width
  • height
◄width1024►
◄height1024►
◄prompt►
◄meta►
◄canvasnone►
◄elements_data►
◄style_palette_data►
◄bg_brightness25►
◄import_modewhen empty►
◄output_formatcompact►
◄import_json►

What you actually installed

MOSS-Image doesn't take a paragraph and figure out the layout. It takes a layout - a JSON document with a scene caption at the top and a list of items under it, each one a box in absolute pixels with a label, a caption, and (for text elements) the literal words to render. The model then draws that, and if you hand it prose instead you've thrown away the part of the model people were excited about.

So you need something that turns words on a canvas into that JSON. ComfyUI core ships Create Bounding Boxes, which builds the same format by hand-wiring coordinates. MossImagePromptBuilderKJ is the friendly version: an editor inside one node where you drag boxes, click one, and type its caption. If you've used the pack's Ideogram 4 Prompt Builder, this is the same canvas in different clothes: Kijai's builder was what people reached for within a day of Ideogram's weights landing, because this JSON is miserable to hand-write.

How it works

The editor is a JS widget that ships with the pack. When you draw boxes it serialises them into elements_data - a string you never hand-edit. On execute, the node walks the boxes and builds the layout the MOSS compiler expects: a summary object (caption, plus optional meta, canvas, palette) and an items array where each entry carries label (object, character or text - set by the box's type toggle), a caption, a text field only for text-labelled boxes, optional tags and per-item palette, and a bbox written as [y_min, x_min, y_max, x_max] in absolute pixels measured from the canvas centre, tagged bbox_coord_space: "abs_centralized" and bbox_format: "yxyx".

Two consequences. Boxes are pixels, not percentages, so width/height must be the size you're actually generating at. And with no placed boxes there's no layout - the node passes your prompt through as plain text, which is the usual "this node does nothing" moment.

Inputs and outputs that matter

The rest is editor plumbing - elements_data, style_palette_data, bg_brightness, output_format - advanced and socketless because the canvas writes them.

The ones you touch:

  • prompt - the scene and style description for the whole image (summary.caption). Write this like a normal prompt; the boxes handle the rest.
  • width / height - multiples of 16, and they must match your generation size. Wire the node's own width/height outputs into your empty-latent or generation-size inputs and you can't desync them.
  • meta and canvas - optional summary fields. meta is a comma-separated tag list (poster, photograph); canvas is none, single, multi_panel or collage. Leave it at none unless the layout is genuinely multi-panel.
  • import_json + import_mode - feed a layout JSON in from elsewhere and it seeds the editor. when empty means the editor wins once you've drawn anything; always makes the wired JSON authoritative on every run.
  • image - a background for the canvas and behind the preview. Useful for blocking a layout out over a reference.

Outputs: prompt (STRING - the layout, into the text encode that feeds the sampler), preview (IMAGE - the box overlay, send it to Preview Image), bboxes (BOUNDING_BOX - pixel boxes other nodes can consume, or a second builder seed), and width / height (INT, per above).

Installing it

KJNodes is in ComfyUI Manager - search "KJNodes for ComfyUI", install, restart. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-KJNodes
pip install -r ComfyUI-KJNodes/requirements.txt
# portable install instead:
# python_embeded\python.exe -m pip install -r ComfyUI\custom_nodes\ComfyUI-KJNodes\requirements.txt

That's five small pip packages - pillow, color-matcher, matplotlib, mss, opencv-python-headless - no torch, no compilation, and no weights: MOSS-Image and its text encoder are a separate download. Restart, and hard-refresh the browser tab, because the canvas is a front-end extension and a cached tab shows you a node with no editor in it.

It's built on ComfyUI's newer node schema and pairs with core's MOSS support, so a few-months-stale install may refuse to register it at all.

Where people get burned

The prompt output is still prose. No boxes were placed, or they have no bbox - unplaced boxes are skipped on export by design.

Boxes land in the wrong place. width/height don't match the generation size. Boxes are absolute pixel edges from the centre, so a mismatch rescales nothing - it misplaces everything.

The layout gets rewritten. Turn the prompt upsampler off when you're using layouts. It rewrites them.

A wired import_json looks ignored. With import_mode on when empty, the editor wins the moment it has boxes. Switch to always.

One thing worth doing on day one: put (phrase:weight) inside box captions and send prompt through MossImagePromptWeight instead of straight to the encoder. That node strips the markup and applies the weight where the encoder can't - on an LLM text encoder, bare (word:1.3) is just punctuation it reads out loud.

CategoryKJNodes/text

Inputs (13)

NameTypeDefaultDescription
widthINT102464–16384Generation width: the boxes are placed in its pixels. Multiples of 16.
heightINT102464–16384Generation height: the boxes are placed in its pixels. Multiples of 16.
promptSTRINGDescription of the whole scene and its style (summary.caption).
metaSTRINGOptional comma-separated tags for summary.meta, e.g. "poster" or "photograph" (blank = omitted).
canvasCOMBOnoneOptional summary.canvas: single image, multi_panel or collage (none = omitted).
elements_dataSTRINGSerialized boxes from the editor (managed by the node UI).
style_palette_dataSTRINGSerialized summary palette from the editor (managed by the node UI).
bg_brightnessINT250–100Background image brightness % (managed by the node UI slider).
import_modeCOMBOwhen emptyHow a wired import_json is used: 'when empty' only seeds the editor while it has no boxes (then the editor wins, so you can edit); 'always' makes the wired JSON authoritative.
output_formatSTRINGcompactOutput JSON formatting (set via the editor toolbar): 'compact' (default) or 'pretty' (indented, for readability).
imageoptIMAGEOptional background for the editor canvas (and behind the preview).
import_jsonoptSTRINGOptional: a MOSS-Image layout JSON. When connected, it loads into the editor and drives the output per 'import_mode'.
bboxesoptBOUNDING_BOX[object Object]Optional pixel-space boxes ({x, y, width, height}) used to seed the editor when it has no boxes. Ignored once boxes exist.

Outputs (5)

NameTypeDescription
promptSTRING—
previewIMAGE—
bboxesBOUNDING_BOX—
widthINT—
heightINT—