ApoGalleria-NL
Turn a structured Ideogram 4 caption into prose for everything else
- nl_prompt
Z-Image Turbo, Krea 2, Qwen-Image, Flux 1, WAN 2.2 and Magic WAN all want roughly the same thing from a prompt - flowing, descriptive sentences. Flux.2 wants that too when you run it in natural-language mode rather than its JSON mode. So instead of shipping five almost-identical converters, the author shipped one with a dropdown.
If you've curated a caption in ApoGalleria-Ideo4, this gets that same content into every other model in your workflow without you writing it twice.
Why prose, not JSON
Because on these models the encoder is an LLM reading your prompt as an instruction, not as a bag of tags - and prose with explicit ownership and spatial relations is what it was built to read. Prompt weighting is inert on all of these encoders, negatives do nothing at CFG 1, and AND/BREAK are dead weight. Sentences and word order are the control surface.
Which is the whole point: structured JSON is a great way to store detail, and not how most models want to receive it.
The mechanism
Input is the export_json string from ApoGalleria-Ideo4. Output is a single continuous paragraph - no line breaks, no Subject: labels, no leftover field names.
How it composes:
It resolves hex colours into names. Ideo4 captions store color_palette as hex codes, which read as noise in a sentence. Each value is matched to its nearest named colour, so #F4E1C1 becomes "warm cream" inside a clause like "in tones of warm cream, sage green, and burnt terracotta." Duplicate names are collapsed, and raw hex never appears in the output.
It reconstructs on-image text, position included. Elements carrying a text field (signage, titles, labels) get folded into their clause as the text "…" is visible in the upper-left. Casing is preserved exactly as written in the source, because that casing usually is the rendered result. The position phrase comes from the element's real bbox, crudely mapped to a 3×3 grid ("upper-left", "centered", "lower area"); no bbox, no position clause - it's omitted rather than guessed. Missing fields are skipped throughout, and nothing is fabricated to fill a gap.
Inputs, outputs, and the preset
ideo4_json is required and socket-only (the code declares it forceInput) - wire Ideo4's export_json into it.
preset is a required dropdown with exactly two options - the only creative decision on the node:
subject-first(default) - opens with the people and objects as one flat listed clause, then background, then style, then lighting.scene-first- establishes the scene first (overall description, then background), then places the subject inside it ("Within this setting, a young woman…"), then style, then lighting.
This is a genuinely different narrative shape, not a reshuffle of the same clauses, and it's the closest thing here to a second seed - flipping it changes how the prompt lands in a way a seed change often doesn't. Images about a place tend to read better scene-first; images about a person, subject-first.
The output is nl_prompt (STRING) - wire it into the text encoder for whichever of those architectures you're running.
Installing it
Part of the pack, so no separate download:
- ComfyUI Manager → search
ApoGalleria→ install. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/ApoloniArt/ApoGalleria ComfyUI-ApoGalleria
pip install -r ComfyUI-ApoGalleria/requirements.txt
- Restart - all three nodes land under the ApoGalleria category.
Dependencies are literally Pillow>=9.0.0 - no models, no extra runtime. Updating is a git pull in the pack folder.
Gotchas
Long output, small context budgets. This composes the entire caption. On attention-limited models that matters: past roughly 75–100 effective tokens, Z-Image-family models start drifting, and a full caption paragraph sails past that. If your nl_prompt is four sentences and the model ignores half, trim the caption in Ideo4 rather than fighting it downstream.
A parse failure returns text, not an error. A malformed input yields a string starting ERROR: … on the output instead of a red node. Useful when debugging a blank generation - read the actual string.
Update if you're on an older clone. v1.0.2 fixed the converter silently dropping elements[].text, which meant images with signs or titles rendered without that text at all. Missing on-image text means you're on the old build.
The preset is required, so pick one. No "unset" option; leave it on subject-first if you like.
Nothing to see in the node itself. No UI, no gallery, no library - all of that lives in ApoGalleria-Ideo4. And the pack is brand new and barely discussed anywhere, so the README and the source are your documentation.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| ideo4_json | STRING | — | |
| preset | COMBO | 2 options: subject-first, scene-first |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| nl_prompt | STRING | — |