πΎ Save Batch Images (BC/NM/POS)
Dump Your BC/NM/POS Passes to Disk Without Clicking Six Times
- bc
- nm
- pos
- preview
What it's actually for
A texture-projection workflow produces three related passes per camera view: base colour, normal map, and position. ComfyUI's built-in SaveImage has no idea they're related - you'd be chaining three save nodes, juggling filename_prefix to keep view1_bc and view1_nm distinguishable, and hoping nothing collides when the batch is six views deep.
This node takes all three as separate optional inputs on one node, writes them with a consistent naming scheme, and hands the whole thing back as one batched image for a preview widget. It's the boring plumbing that keeps a multi-view pipeline sane.
How it works
Feed it bc, nm, and pos batches and it loops each one, converts each tensor to a PIL image, and writes:
{build}/output/view_bc_1.png
{build}/output/view_bc_2.png
{build}/output/view_nm_1.png
...
So filename plus the channel plus the index - deterministic, greppable, and matching what the pack's Load_batch_images and View2DSaveLoad expect to find. Saving uses PNG with compress_level=1, i.e. fast rather than small; that's a deliberate choice for iterative work, and it means these files are chunkier than you'd expect. There's no metadata embedding here - no workflow chunks, no A1111 parameters - so these are working files, not something you'd upload to Civitai and expect to reconstruct from. Keep your graph saved separately.
Two behaviours worth knowing:
- All three inputs are optional. If all are empty, it returns a 16x16 black placeholder tensor instead of erroring.
- The 16x16 gate. Before writing anything, the node inspects the first available channel and refuses to write if the image is 16px or smaller on either side. That's a deliberate guard for the pack's own pipeline, where the batch-listing node emits tiny placeholder images to keep a graph's structure valid. Useful in-context, mildly surprising if you ever legitimately want to save a 16x16 texture - you can't.
The output is preview: every image written, stacked into one batch, so you can drop a Preview Image node on it and see the lot.
The inputs that matter
- path (default
L:/AI_3d/output) - a raw filesystem path, not ComfyUI's output folder. It's the author's drive; change it or your files land nowhere useful. The node creates the directory if it doesn't exist. - filename (default
view) - the base name. Keep it short; it prefixes every file in the batch. - bc / nm / pos - the three image batches. Wire whichever you have; each is written independently, so a graph with only base colour still works.
One output: preview (IMAGE), the concatenated batch for a viewer.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Antonioilev/ComfyUI_Antonioilev_Lightpack.git
# restart ComfyUI
Manager search: "Antonioilev Light Pack". The repo ships no requirements.txt and __init__.py catches import errors with only a printed node count, so a missing package shows as a missing node. This one is torch, numpy and Pillow - all present in any ComfyUI install.
Where people get burned
- The path is absolute by default and won't exist on your machine. Set it to a folder you own. Windows-style
L:/...paths work if you're on Windows; on Linux, use a real mount. IS_CHANGEDreturns the current time, so this node re-runs and re-writes every queue, even when nothing upstream changed. That's intentional for a saver, but it means a graph left running overnight fills a folder.- Files are large.
compress_level=1trades size for speed - if you're archiving, re-compress afterwards or swap in a standard save node for the final pass. - No alpha. Wire a batch that has an alpha channel and it's flattened into RGB on save. That's what the pack's alpha variant is for.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| path | STRING | L:/AI_3d/output | β |
| filename | STRING | view | β |
| bcopt | IMAGE | β | |
| nmopt | IMAGE | β | |
| posopt | IMAGE | β |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| preview | IMAGE | β |