ComfyUI Node
AM Write Image
A ComfyUI node in AM VFX Tools with 30 inputs and 9 outputs.
AM Write Image
- image
- mask
- video
- image
- mask
- resolved_path
- info
- width
- height
- frame_rate
- frame_count
- video
◄file_path►
◄extexr►
◄seed-1►
◄use_batchfalse►
◄frame_modeall►
◄frame_rate-1.00►
◄use_frame_numberstrue►
◄first_frame1►
◄last_frame-1►
◄start_frame1001►
◄frame_padding5►
◄bit_depth16f►
◄compressionexr/dwaa►
◄working_colorspaceDisplay/sRGB - Display►
◄raw_datafalse►
◄output_colorspaceACES/ACES2065-1►
◄embed_workflowtrue►
◄reformat_modeoff►
◄scale1.00►
◄presetWidth/Height►
◄target_width1920►
◄target_height1080►
◄resize_typefit►
◄filtercubic►
◄output_dtypefp16►
◄show_previewtrue►
◄load_saved_from_diskfalse►
CategoryAM VFX Tools
Inputs (30)
| Name | Type | Default | Description |
|---|---|---|---|
| file_path | STRING | Absolute output path. The `ext` widget below picks the file format. Use the 📂 Browse button for the native dialog. | |
| ext | COMBO | exr | Output file format. Drives the on-disk extension and the OIIO writer plugin selected for the encode. |
| seed | INT | -1-9223372036854776000–9223372036854776000 | Generation seed — metadata-only, never in the filename. -1 = look up the AM Seed registry by id(prompt). Any other value (typed or wired) wins over the registry. |
| use_batch | BOOLEAN | false | When On, append a runtime-discovered `_bNNNN` suffix (queue-iteration counter, scanned from the output dir). Off = no suffix; queue iterations overwrite each other. |
| frame_mode | COMBO | all | Which input batch frames to write. single = only `first_frame`. range = `first_frame`..`last_frame` inclusive. all = every frame in the input batch. |
| frame_rate | FLOAT | -1.00-1–480 | Frame rate metadata for the written sequence. -1 = don't write any fps metadata (default). Any other value writes `framesPerSecond` (EXR canonical Rational) AND `input/frame_rate` (Nuke convention) into the file header. Wire AM Read Image's `frame_rate` output here for full sequence roundtrip. |
| use_frame_numbers | BOOLEAN | true | When On, the filename embeds a frame digit — produces a numbered sequence (e.g. `...img.01001.exr`). Off = single-image save, no digit; multi-frame batches will collapse onto the same path (warning logged). |
| first_frame | INT | 11–999999 | Input batch index (1-based) for single mode; lower bound for range mode. Ignored in all mode. |
| last_frame | INT | -1-1–999999 | Input batch upper bound (1-based, inclusive) for range mode. -1 = auto = batch length. |
| start_frame | INT | 1001-999999–999999 | First OUTPUT frame number embedded in the filename. Default 1001 (VFX convention — leaves a 1000-frame leader for handles / re-times). Ignored when `use_frame_numbers` is Off. |
| frame_padding | INT | 51–12 | Digit width of the frame token (default 5 → `01001`). Applied when `use_frame_numbers` is On. |
| bit_depth | COMBO | 16f | Output numeric type per channel. 8 = uint8 (LDR formats). 16 = uint16 (TIFF/PNG hi-bit). 16f = half-float (EXR default — recommended for VFX). 32f = full float (rare; very large files). |
| compression | COMBO | exr/dwaa | EXR compression algorithm — other formats ignore this. zip/zips/piz = lossless. dwaa/dwab = lossy (~3-4× smaller, perceptually invisible for AI/proxy work). rle = run-length. none = uncompressed (largest). |
| working_colorspace | COMBO | Display/sRGB - Display | Source colorspace — the space the upstream IMAGE tensor is in. The OCIO transform converts from this to `output_colorspace`. |
| raw_data | BOOLEAN | false | When On, skip the OCIO transform — pixels written verbatim. `working_colorspace` and `output_colorspace` are ignored. |
| output_colorspace | COMBO | ACES/ACES2065-1 | Destination colorspace. The OCIO transform converts to this, and the value is written into the file as the `oiio:ColorSpace` tag for downstream readers. |
| embed_workflow | BOOLEAN | true | Embed the API graph (`comfyui/prompt`) as file metadata so the file is round-tripped via AM-Pipe drag-drop. Off = clean deliverable without workflow JSON. Honors ComfyUI's global `--disable-metadata` flag. |
| reformat_mode | COMBO | off | Reformat mode. off = bypass, output matches input. scale = uniform scale by `scale` (other widgets ignored). to_box = resize/crop to a target W×H from `preset` or `target_width`/`target_height`. |
| scale | FLOAT | 1.000.01–16 | Uniform scale factor. Used when `reformat_mode=scale`; ignored otherwise. Output dimensions are round(input × scale). |
| preset | COMBO | Width/Height | Named output format. Used when `reformat_mode=to_box`. `Width/Height` = use the `target_width` / `target_height` widgets below. Any other entry overrides those widgets with the preset's resolution. |
| target_width | INT | 19201–16384 | Target output width in pixels. Used when `reformat_mode=to_box` AND `preset=Width/Height`; ignored when a named preset is selected. |
| target_height | INT | 10801–16384 | Target output height in pixels. Used when `reformat_mode=to_box` AND `preset=Width/Height`; ignored when a named preset is selected. |
| resize_type | COMBO | fit | How input maps into the target box. Used when `reformat_mode=to_box`. width/height = scale uniformly to match that edge. fit = scale to fit inside the box (letterbox; black where the box exceeds the scaled image). fill = scale to cover the box (crops the overflow). distort = scale W and H independently to exactly match the box (changes aspect). none = no scale; place input centered in the box (crop if larger, pad if smaller). Cropped-away/padded regions are TRANSPARENT — RGB sources are promoted to RGBA with alpha=0 in the padded area so downstream compositing is clean. |
| filter | COMBO | cubic | Pixel filter for resampling. impulse = nearest-neighbor (mask passes, exact pixel preservation). linear = bilinear (cheap, smooth). cubic = bicubic (default; the safe Nuke-equivalent). Lanczos4 = sharpest; for high-quality stills / final delivery. area = best for downscaling — anti-aliased mean pooling, softer but artifact-free. |
| output_dtype | COMBO | fp16 | Output tensor dtype. fp32 = ComfyUI default (4 bytes/sample). fp16 = half memory + half VRAM (2 bytes/sample). EXR-native precision; fits the [0,1] LDR + scene-linear range with headroom up to ~65504. Some downstream nodes assume fp32 — flip back to fp32 if you hit dtype errors. |
| show_preview | BOOLEAN | true | Show a thumbnail of the first written frame on the node. |
| load_saved_from_disk | BOOLEAN | false | OFF (default): write upstream IMAGE batch to disk. ON: skip the write entirely, re-read from disk the files at the same paths the Write would resolve, and apply the INVERSE OCIO transform to land back in `working_colorspace`. Upstream nodes feeding the image/mask inputs are NOT evaluated when ON — the Write node behaves as a Read node. IMAGE output is in `working_colorspace` in BOTH modes (the OCIO transform is scoped to the disk write; downstream nodes always see working-cs). Honors `raw_data` (skips OCIO both ways). |
| imageopt | IMAGE | Image batch to write. | |
| maskopt | MASK | Optional alpha channel as MASK (N×H×W float in [0,1]). MASK CONVENTION (stock ComfyUI): mask = 1 - alpha white (1.0) = 'area to inpaint' (source was transparent) black (0.0) = 'keep' (source was opaque) empty mask = all zeros (source has no alpha = fully visible) This is the SD-inpainting convention every stock ComfyUI mask-using node expects (LoadImage, MaskComposite, SetLatentNoiseMask, ImpactPack mask pipeline, etc.). Drop-in compatible with all of them. If you want NUKE-STYLE natural alpha (mask = alpha, where 1.0 = opaque), wire a MaskInvert node between this socket and your downstream consumer. When wired, the file is encoded with alpha = 1 - mask. Mismatched mask dimensions are auto-resized (cubic) to match the image's H,W. When the input IMAGE is already 4-channel and a MASK is also wired, MASK overrides the embedded alpha. Per-format support: RGBA writes natively to EXR / PNG / TIFF. JPG / HDR silently strip the alpha channel at the OIIO writer (but the MASK output still carries the right data). | |
| videoopt | VIDEO | Optional VIDEO input. When wired, iterates the source frame-by-frame via PyAV and writes each EXR — peak RAM stays at ONE frame regardless of source length. Per-frame OCIO + Reformat + dtype apply (driven by this node's widgets). Upstream image/mask are lazy-skipped. MASK is dropped — write RGB only; wire `image` if you need mask handling. `VideoFromComponents` upstream works but with reduced RAM benefit (batch already in memory). |
Outputs (9)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Sliced IMAGE passthrough — the input image post-frame-slice / post-mask-fold / post-reformat, in `working_colorspace`. The OCIO transform is scoped to the disk write only; downstream nodes see the same colorspace as the upstream chain. RGB only. |
| mask | MASK | MASK passthrough — the alpha that was written to disk (or would have been, if the codec supports alpha). MASK CONVENTION (stock ComfyUI): mask = 1 - alpha white (1.0) = 'area to inpaint' (source was transparent) black (0.0) = 'keep' (source was opaque) empty mask = all zeros (source has no alpha = fully visible) This is the SD-inpainting convention every stock ComfyUI mask-using node expects (LoadImage, MaskComposite, SetLatentNoiseMask, ImpactPack mask pipeline, etc.). Drop-in compatible with all of them. If you want NUKE-STYLE natural alpha (mask = alpha, where 1.0 = opaque), wire a MaskInvert node between this socket and your downstream consumer. Sources, in priority order: 1. The wired `mask` input (if any). 2. Embedded alpha from a 4-channel IMAGE input. 3. Empty mask (zeros) — input was 3-channel with no MASK wired. Sized + reformatted to match the IMAGE output. Useful when chaining another node after a Write without re-reading from disk. |
| resolved_path | STRING | Newline-joined absolute paths of every file written this execute. |
| info | STRING | Human-readable summary: dimensions, bit depth, output colorspace, count. |
| width | INT | Frame width in pixels. |
| height | INT | Frame height in pixels. |
| frame_rate | FLOAT | Frame rate widget passthrough — the value written into file metadata (-1 = no fps metadata was emitted). |
| frame_count | INT | Number of files written. |
| video | VIDEO | VIDEO passthrough — when the IMAGE branch fired, wraps the IMAGE batch in a `VideoFromComponents` (zero copy). When the VIDEO branch fired, emits the input VIDEO as-is. None on no-op. Lets graphs chain post-write VIDEO downstream without re-reading. |