Nodes/MOSS Layout UI/MOSS 构图布画 · Tag 画笔
ComfyUI Node

MOSS 构图布画 · Tag 画笔

Draw the boxes instead of typing yxyx coordinates

By MIKOU306·Created 22 days ago·Updated 19 days ago· 18
MOSS 构图布画 · Tag 画笔
    • layout
    • preview
    ◄width1088►
    ◄height1920►
    ◄state►

    MOSS-Image takes layout as prompt. Literally: you feed it JSON with a summary and a list of items, each with a caption and a bbox in [y_min, x_min, y_max, x_max] integer pixels measured from the canvas centre. On a 1024² canvas that's numbers between −512 and 512, and your first hour with the model is spent typing [358, -320, 493, 320] and guessing which corner moved. MOSSLayoutCanvas is the fix. You drag boxes on a panel; the node hands back the layout.

    This is the first of three nodes that ship together as a set: Canvas → Elements → StandardPrompt → your positive CLIPTextEncode. This article is only about the drawing board.

    Why a canvas at all

    Box-conditioned generation is the thing regional prompting spent three years working around - masking attention per region because a prompt has no sense of where. A model that takes boxes as part of its caption schema skips the workaround; Ideogram 4 is the commercial proof, MOSS-Image the open-weight attempt. The catch: it hands you a JSON schema and no editor. That's the gap this pack fills, and it's niche enough that there's no tutorial footprint yet - expect to read the README, not a video.

    How the canvas actually works

    The panel is a DOM overlay drawn by the pack's frontend code, not a ComfyUI image widget. Everything you drag gets written into the hidden state string as a moss-layout/v1 object using percent [left, top, width, height]. That percent storage is why resizing is cheap: boxes stay put proportionally, and nothing needs re-laying-out.

    On execution the backend parses state, re-applies the current width/height, and returns two things - the layout JSON as a string, and a raster preview baked with PIL: dark grid, each box in its tag colour with a numbered label. That preview is a diagram of your plan, not a render of your picture - nice for catching the stray 2%-wide box you forgot about.

    The inputs and outputs that matter

    width and height are the ones you actually touch - both INT, default 1088 × 1920 (a poster-shaped default that tells you who this pack is for), step 16, up to 16384. Wire a PrimitiveInt into each and canvas size comes from upstream; the README notes PrimitiveInt, the frontend PrimitiveNode and Reroute all chain through.

    state is the hidden widget holding the layout JSON; you never type in it. It's what saves the layout with the workflow instead of in browser storage, and the backend reads it as a fallback when nothing is wired in.

    Outputs: layout (STRING) goes into MOSSLayoutElements.layout and MOSSLayoutStandardPrompt.layout - skip either and the three nodes stop sharing one layout. preview (IMAGE) goes into a Preview Image node if you want to eyeball the composition before spending a sampling run.

    Installing it

    ComfyUI Manager, search MOSS Layout UI, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/MIKOU306/ComfyUI-MOSS-Layout-UI.git comfyui-moss-layout-ui
    

    Restart ComfyUI, then Ctrl+F5 in the browser. That hard reload isn't optional - the panel is JavaScript shipped in web/, and a cached older copy looks exactly like a broken node.

    Dependencies are genuinely nothing: pyproject.toml has an empty dependency array, and the pack leans on the torch, numpy and Pillow ComfyUI already ships. It does need a build exposing the new node API (comfy_api.latest) - the author develops against ComfyUI 0.41.0 / frontend 1.55.18. On an older ComfyUI the nodes won't register at all, which reads as "pack broken" but isn't.

    No weights in the repo, by design. The example workflow loads an INT8 diffusion model from models/diffusion_models, a Qwen3.5 INT8 text encoder from models/text_encoders and a Flux2 small VAE from models/vae - fetch those separately.

    Where people get burned

    Two copies of the pack. If you installed a folder named moss-layout-ui by hand before the Registry version existed, move it out of custom_nodes. Duplicate loads behave strangely, and the StandardPrompt node warns about them.

    Canvas size ≠ generation size. Percent storage survives resizing, but abs_centralized bboxes are measured against the canvas the prompt was compiled for. Match your empty latent to the canvas, or the coordinates mean something else.

    Rectangles only. MOSS-Image's bbox is four integers - no mask channel in the format. Circles and polygons aren't a missing feature; they can't be expressed. Approximate tight selections with smaller rectangles.

    Tags are not labels. The editor offers 主体 / 人物 / 文字 / 图片 / 装饰 / 版式, but the model only knows object, character and text. Image, decoration and layout boxes all compile as object - put the extra meaning in the element's tags.

    The background isn't a box you generate. Element 0 is always the fixed full-frame background, pinned at [0, 0, 100, 100], and never becomes an item. Its description merges into summary.caption - right for "on a rain-slicked neon street", wrong if you expected a background object.

    CategoryMOSS Layout

    Inputs (3)

    NameTypeDefaultDescription
    widthINT108816–16384—
    heightINT192016–16384—
    stateSTRINGLayout JSON written by the node UI and saved with the workflow.

    Outputs (2)

    NameTypeDescription
    layoutSTRING—
    previewIMAGE—