Nodes/kubakub nodes/kubakub regions from illustrator
ComfyUI Node

kubakub regions from illustrator

Read the client's Illustrator file directly, layers and all

By kubakubkub·Created about a month ago·Updated 2 days ago· 10
kubakub regions from illustrator
  • matrix
  • scope
  • regions
  • preview
  • lines
  • reference
  • layer_masks
  • layer_names
  • scope_mask
  • regions_json
  • report
◄ai_file►
◄min_region_area400►
◄merge_small_regionstrue►
◄line_gap_close_px1►
◄split_shapestrue►
◄scale1.00►
◄layer_roles►

If you work on real projection jobs, this is the node that saves you the most time. Client hands you a layered Illustrator file: an outline layer, a mask layer that says what's in range, a placed photo of the building, a layer of obstacles, and the text layer nobody can delete. Your job is now "one region per window, but only inside the mask". Manually exporting PNGs per layer, per shape, is a whole evening with After Effects.

This node reads the .ai straight through - every layer, hidden ones included - and gives you the atlas.

What it does with each layer

The mechanism is worth a paragraph because it explains the node's accuracy. .ai files are PDF-compatible by default, so the pack uses PyMuPDF to read the PDF inside. It then switches every layer on in memory (hidden layers are read too, which is not what Illustrator shows you and is usually what you want), and rasterises each layer by replaying its own paths rather than soft-proving a flattened render. Curves, compound shapes with even-odd holes, and stroke widths therefore come out exact.

Then it guesses a role per layer from the content, which is the part that will surprise you pleasantly:

  • lines - mostly stroked paths. These get cut into the closed cells between the lines, named <LAYER>_001 upward in reading order, grouped by shape (<LAYER>_g3) so repeated windows share a group, and tagged with the layer name.
  • shapes - mostly filled paths. One region per separate shape, <LAYER>_01, placed on top and cutting into the cells below.
  • outside / scope - masks that bound the projection, guessed from a name containing mask/range/scope/matte: touching the border means "never a region", not touching means "only here".
  • reference - placed images. Those go out on the reference output, at their artboard position.
  • ignore - a full-artboard fill, live text, or a name starting with _.

The report lists every layer with its guessed role, its path count and how many pixels it covers, so you can check the guess in ten seconds instead of discovering it later.

When the guess is wrong, layer_roles overrides it, one line per role, wildcards fine:

CENTRE, COUR, JAR = lines
MASK_1 = outside
OBSTACLES = shapes

split_shapes decides whether shape layers give one region per separate shape or one per layer. line_gap_close_px thickens lines by a pixel before filling so small gaps in the drawing don't leak one cell into the next - the same family of problem regions from sketch solves for hand drawings, and worth raising if your file has a cell bleeding into its neighbour. An scope mask input bounds everything as usual.

Scaling, and the outputs

The artboard maps onto the matrix with one uniform scale - never stretched, and the artboard has to match the matrix aspect or the node refuses. Without a matrix, scale sets pixels per point (1 = artboard size). The file's date and size are part of the cache key, so re-saving the .ai re-runs the node, which is the behaviour you want and will occasionally surprise you.

Outputs beyond regions: preview (grouped colours, borders and ids over the matrix, the photo, or the drawing), lines (the line layers white on black - a control image you can feed downstream), reference (the placed photo), layer_masks and layer_names (every layer with paths, as a mask batch), scope_mask, regions_json, and report.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/kubakubkub/ComfyUI_KubaNodes
python -m pip install -r ComfyUI_KubaNodes/requirements.txt
python -m pip install PyMuPDF

Manager → kubakub nodes, or comfy node install comfyui-kubanodes. ComfyUI 0.37.0+. PyMuPDF is not in requirements.txt - the pack deliberately keeps optional packages out, so only this node and vector PDF output need it, and the startup console tells you it's missing. If the node errors on load, that's the fix.

Model-free test: tests/test_illustrator.py writes a small layered PDF with PyMuPDF and reads it back, so you can confirm the whole path before touching the client's file.

The limits, stated plainly

Live text is not a path. If text in the file is real text rather than outlined, it isn't a region. Outline it in Illustrator, or accept that it's ignored.

Only the first artboard is read.

Dense ornament becomes many small cells. The README's own example: a balustrade turns into a lot of tiny cells, and the fix is raising min_region_area, not fighting the tracer.

A few cells along the edge can end up outside every layer's outline and get named lines_…. Harmless, but confusing the first time you see it in the preview. The pack's own test is a good reference point for what "working correctly" looks like: an 8-layer, 5094-path facade, three hidden line layers, all roles guessed right, and the MASK layer matching the festival's own PNG export to 99.96%.

Categorykubakub/2d/regions

Inputs (9)

NameTypeDefaultDescription
ai_fileSTRINGPath of the .ai or .pdf (Explorer 'Copy as path' quotes are fine).
min_region_areaINT4000–100000000Cells and shapes smaller than this (pixels) are merged into a neighbour or dropped.
merge_small_regionsBOOLEANtrueOn: merge small cells into the neighbour with the longest border. Off: drop them.
line_gap_close_pxINT10–32Thicken the lines by this much first, so small gaps in the drawing don't leak one cell into the next.
split_shapesBOOLEANtrueShape layers: one region per separate shape (on) or one region per layer (off).
scaleFLOAT1.000.05–16Without matrix: pixels per point (1 = the artboard size in points).
matrixoptIMAGEThe matrix: sets the output size (the artboard must have its aspect) and is the preview background.
layer_rolesoptSTRINGOptional, one line per role: '<layer names or wildcards> = role'. Roles: lines (cells between the lines), shapes (one region per filled shape, on top), outside (not projected on), scope (only here), tag (tags the regions it covers), reference (photo output), ignore. Layers not listed get a role from their content (see the report).
scopeoptMASKPixels outside this mask are never part of a region.

Outputs (9)

NameTypeDescription
regionsKUBA_REGIONSLabel map + region table for the kubakub region nodes.
previewIMAGEOne colour per group, region borders and ids over the matrix, the photo or the drawing.
linesIMAGEThe line layers, white on black (a control image).
referenceIMAGEThe placed photo (reference layers); black if none.
layer_masksMASKEvery layer with paths as a mask (what it covers).
layer_namesSTRINGNames of layer_masks, one per line.
scope_maskMASK1 where regions may be.
regions_jsonSTRINGThe region table as text, with the layer list.
reportSTRINGEvery layer with its role, paths and covered pixels, and regions per layer.