Nodes/lf-nodes/Save DDS
ComfyUI Node

Save DDS

Get your textures into the game engine's format

By lucafoscili·Created 2 years ago·Updated a day ago· 35
Save DDS
  • image
  • ui_widget
  • file_names
  • receipt
filename_prefixLF_Nodes/DDS
pixel_formatRGBA32
mip_policynone

So you generated a texture and you want it in the game. If that game is anything Unreal, Unity, or a modded title with its own texture pipeline, "in the game" often means DDS - the DirectDraw Surface format GPUs and game engines actually prefer. ComfyUI's built-in savers give you PNG and JPG. LF_SaveDDS is the pack's answer for when PNG isn't the destination.

It's deliberately a serialization-only node, and the author is explicit about the division of labor: upstream nodes own the pixels, canvas, resizing, and any consumer-specific export profile; this node just encodes whatever RGB/RGBA batch it's handed into DDS files under ComfyUI's output directory. That's the right design - DDS encoding is fiddly enough that you want one well-tested writer rather than a kitchen sink. It's also CPU-only, so it won't touch your GPU.

Formats: the four choices

  • RGB24 - uncompressed RGB, 8 bits per channel (legacy BGR byte layout). Biggest files, zero compression loss.
  • RGBA32 - uncompressed RGBA with alpha (legacy BGRA). The default, and the sensible default.
  • BC1 (aka DXT1) - block compression, opaque input only. If you feed it RGBA with any non-opaque alpha, encoding fails with invalid_alpha rather than silently dropping transparency.
  • BC3 (aka DXT5) - block compression with alpha, the legacy texture-compression workhorse.

The tooltips are careful about naming: "RGB8"/"RGBA8" are per-channel descriptions, not separate wire values, and DXT1/DXT5 are legacy aliases for BC1/BC3.

Inputs and outputs

  • image - RGB or RGBA batch. Float tensors are moved to CPU, clamped, quantized (round-half-up); native uint8 passes through untouched.
  • filename_prefix - output-relative path and prefix, default LF_Nodes/DDS. .dds plus a collision-safe counter is appended automatically.
  • pixel_format - one of the four above.
  • mip_policy - none saves only the source level; full_chain floor-halves each dimension down to 1×1 (a 1920×1080 texture yields 11 levels), resampled with Pillow's LANCZOS, pinned at the pack's 12.2.0 version. Full mip chains are what game engines typically want.

Alpha never gets silently dropped: RGBA32/BC3 preserve it, RGB input gets an explicit opaque alpha channel, and RGB24/BC1 refuse to encode unless alpha is fully opaque. Outputs are file_names (an ordered list of output-relative .dds paths - feed them to LF_RegisterOutputFile if you want them in history) and receipt, a deterministic lf.dds.receipt.v1 record of format, mip policy, and alpha handling.

Installing and gotchas

It's one of ~138 nodes in LF Nodes:

cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes.git

restart (or ComfyUI Manager → search "LF Nodes"). Manager installs the pack requirements; the pack pins Pillow to 12.2.0, which matters here since mip resampling is pinned to that exact LANCZOS backend. Pack gotcha as usual: rewritten repo, old one archived in 2025 - clone lucafoscili/lf-nodes.

The realistic failure modes: feeding BC1 an image with any transparency (rejected deliberately), expecting the node to resize/crop for you (it won't - do that upstream), and wondering why your DDS won't load in an engine that wants a specific mip chain or format (pick the format your engine's importer expects; there's no "auto-detect"). If you're doing game/modding texture work this is a genuinely useful bridge - one of the few ways to get ComfyUI output into a DDS pipeline without leaving the graph.

Category✨ LF Nodes/IO Operations

Inputs (5)

NameTypeDefaultDescription
imageIMAGEInput RGB or RGBA image batch to encode as DDS.
filename_prefixSTRINGLF_Nodes/DDSOutput-relative path and filename prefix. Files are always saved with .dds and a collision-safe counter.
pixel_formatCOMBORGBA32RGB24/RGBA32 are uncompressed 8-bit channels; BC1/BC3 are legacy DXT1/DXT5 block compression.
mip_policyCOMBOnoneSave only the source level or a complete floor-halved chain down to 1x1.
ui_widgetoptLF_TREE[object Object]

Outputs (2)

NameTypeDescription
file_namesSTRINGOrdered output-relative DDS filenames.
receiptJSONDeterministic lf.dds.receipt.v1 receipt.