MOSS-Image Prompt Builder KJ
MOSS-Image Prompt Builder KJ
- image
- bboxes
- prompt
- preview
- bboxes
- width
- height
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 ownwidth/heightoutputs into your empty-latent or generation-size inputs and you can't desync them.metaandcanvas- optional summary fields.metais a comma-separated tag list (poster,photograph);canvasisnone,single,multi_panelorcollage. Leave it atnoneunless the layout is genuinely multi-panel.import_json+import_mode- feed a layout JSON in from elsewhere and it seeds the editor.when emptymeans the editor wins once you've drawn anything;alwaysmakes 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.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| width | INT | 102464–16384 | Generation width: the boxes are placed in its pixels. Multiples of 16. |
| height | INT | 102464–16384 | Generation height: the boxes are placed in its pixels. Multiples of 16. |
| prompt | STRING | Description of the whole scene and its style (summary.caption). | |
| meta | STRING | Optional comma-separated tags for summary.meta, e.g. "poster" or "photograph" (blank = omitted). | |
| canvas | COMBO | none | Optional summary.canvas: single image, multi_panel or collage (none = omitted). |
| elements_data | STRING | Serialized boxes from the editor (managed by the node UI). | |
| style_palette_data | STRING | Serialized summary palette from the editor (managed by the node UI). | |
| bg_brightness | INT | 250–100 | Background image brightness % (managed by the node UI slider). |
| import_mode | COMBO | when empty | How 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_format | STRING | compact | Output JSON formatting (set via the editor toolbar): 'compact' (default) or 'pretty' (indented, for readability). |
| imageopt | IMAGE | Optional background for the editor canvas (and behind the preview). | |
| import_jsonopt | STRING | Optional: a MOSS-Image layout JSON. When connected, it loads into the editor and drives the output per 'import_mode'. | |
| bboxesopt | BOUNDING_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)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |
| preview | IMAGE | — |
| bboxes | BOUNDING_BOX | — |
| width | INT | — |
| height | INT | — |