Nodes/ComfyUI-DAELab-Custom-Nodes-Library/GPT-Image-2 Material Region Channel V1
ComfyUI Node

GPT-Image-2 Material Region Channel V1

One region, one billable call, no surprises

By TeutonicMepheles·Created 4 months ago·Updated 6 days ago· 0
GPT-Image-2 Material Region Channel V1
  • base_image
  • flat_image
  • height_map
  • material_region_set
  • region_image
  • region_mask
  • call_status
◄region_slot1►
◄qualitymedium►
◄max_regions4►
◄minimum_region_pixels16►

What it is and why you'd reach for it

Four materials on one badge means four masked edits. The convenient way to build that is a loop node that fires four API calls behind one widget. The problem with the convenient way is that you can't see what it's doing, you can't re-roll one region, and when the run costs money you have no idea which child blew up.

This node takes the opposite approach: it's a visible single-region channel. You get four copies of it on the canvas, slot 1 through 4, each one expanding exactly one native GPT-Image-2 node - and only when its region actually exists. No region in that slot means the node returns your base image and an empty mask, having created no API child at all. That's the "billable-call-aware" bit in the author's description, and it's the right instinct for a pack where every generative hop is metered.

How it works

The material_region_set comes from Badge Material Region V1 (DAELab), which maps source colours in your flat artwork to a material catalogue and emits per-region masks. This node runs the same preflight the executor does: groups with no matched pixels, groups assigned the default transparent_lacquer, groups smaller than minimum_region_pixels, and groups missing a mask are all skipped with a reason. If the number of active regions exceeds max_regions it raises before anything is expanded - a budget guard, not an error about your mask.

region_slot then selects the nth active region, not the nth configured group. That's a distinction worth internalising: if region 1 is transparent lacquer and gets skipped, slot 1 picks region 2. Wire all four channels and read the call_status JSON on each one - it carries region_id, material_id, gpt_node_used and a reason field, so the mapping is auditable rather than guessed.

When a slot does resolve, the node expands a subgraph at execution time (ComfyUI's V3 node expansion): one native OpenAIGPTImageNodeV2 with the region's material prompt, 1024x1024, opaque background, Image 1 = your immutable base, mask = the region mask, seed = the region's reroll_revision; feeding one Badge Material Constraint V1 child with conservative fixed limits. You get the constraint's image and mask out, plus the status. Changing one region's material or re-roll revision invalidates only that channel's cache, so the other three GPT calls are served from cache instead of re-billed.

Inputs and outputs that matter

base_image (must be a single image - this raises on a batch), flat_image (colour reference), height_map, material_region_set, region_slot, quality (low/medium/high, passed straight to the model), max_regions (default 4), minimum_region_pixels (16 by default; raise it if you keep getting edits on stray specks).

Outputs: region_image and region_mask go to the matching slot of Badge Material Region Merge V1, along with call_status - the merge node requires the status string as an input, which is how it can report the true GPT-node count afterwards.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/TeutonicMepheles/ComfyUI-DAELab-Custom-Nodes-Library

Restart. You need ComfyUI's official OpenAI/GPT Image nodes installed and logged in - this node doesn't call the API itself, it grafts a native node into the graph, so if OpenAIGPTImageNodeV2 isn't available the expansion fails. It's also a V3-schema node, so keep core current (No module named 'comfy_api' = update core). OpenCV is required by the module and absent from requirements.txt.

Common issues

  • GPT masked editing requires exactly one immutable base image. You're feeding a batch. Every channel edits the same single base on purpose - that's what makes the regions comparable.
  • Slot 3 does nothing. Fewer than three active regions, or call_status says no_active_region_for_slot. Check the skipped array in the status; it names each skipped region and why.
  • Material API budget exceeded before GPT execution. More than max_regions active regions. Either consolidate regions or raise the cap deliberately - the check exists so a colour-match rule that suddenly hits everything doesn't cost you four calls.
  • A channel returns your image unchanged with a zero mask. Correct behaviour for an empty slot. Wire call_status into a report or text node if you want to see it without opening the node.
CategoryDAELab/Badge/Strict

Inputs (8)

NameTypeDefaultDescription
base_imageIMAGE—
flat_imageIMAGE—
height_mapMASK—
material_region_setBADGE_MATERIAL_REGION_SET—
region_slotINT11–4—
qualityCOMBOmedium3 options: low, medium, high
max_regionsINT41–4—
minimum_region_pixelsINT161–65536—

Outputs (3)

NameTypeDescription
region_imageIMAGE—
region_maskMASK—
call_statusSTRING—